This post is part 2 of my dive into Gradle and Groovy. If you are just getting caught up, check out part 1. You can also skip straight to the code on GitHub.

Since we already talked about Gradle, let's go over my goals for writing a Groovy Broadleaf module:

Write something very self-contained (needed to finish it in a few days)

Operate alongside of our normal Java code in the rest of the Broadleaf framework

See how good the IDE support is (I use Eclipse)

Try to be as idiomatic as possible - make sure my code conformed to The Groovy Way as much as possible

Keeping it small

I decided to bite off an implementation of the FileServiceProvider interface. We had recently finished writing an Amazon S3 provider so that assets and site maps could be uploaded automatically to S3 and I thought that a Rackspace Cloud Files implementation could also be compelling. It also did not require a ton of code and Rackspace was already pushing JClouds to take additional boilerplate out of it.

The environment

I was very impressed with the first-class Groovy and Gradle dependency management support in Eclipse. I installed the following plugins from the Eclipse Marketplace to facilitate this:

Gradle Integration for Eclipse - this gave me a 'Gradle Dependencies' library on my build path just like 'Maven Dependencies' for Maven projects

Groovy/Grails Tool Suite - this gave me a bit better language support for Groovy which was most helpful in the Gradle build file DSL. It included some Grails features that I didn't use but didn't hurt anything to add in

Once I imported in the project, I got a nice build out which looked very similar to my experience with Maven projects

Enabling the DSLD support gave me some code-completion content-assist in my build.gradle file. It was a little sparser than I would have liked and I found myself going back and forth to official documentation for the various plugins I was using:

The code

On to the fun part! Again, I tried to be as idiomatic as I could with my code.

Domain objects and closures

There are a few connection properties to connect to the Cloud Files API. I modeled this as a simple DTO (Domain Transfer Object):

class CloudFilesConfiguration { static final String USERNAME_PROP = ' broadleaf . rackspace . cloudfiles . username ' static final String APIKEY_PROP = ' broadleaf . rackspace . cloudfiles . apikey ' static final String ENDPOINT_PROP = ' broadleaf . rackspace . cloudfiles . endpoint ' static final String CONTAINER_PROP = ' broadleaf . rackspace . cloudfiles . container ' static final String CONTAINER_SUBDIR_PROP = ' broadleaf . rackspace . cloudfiles . containerSubDirectory ' def username def apikey def endpoint def zone def container def containerSubDirectory }

A few things about this snippet:

No getters or setters - Groovy adds getters/setters automatically for you

No scope keywords - Everything in Groovy defaults to the public scope. Combine this with no getters/setters and DTOs just got a hell of a lot simpler

scope. Combine this with no getters/setters and DTOs just got a hell of a lot simpler No semicolons - Semi-colons are optional. Since I was trying to be like Groovy (which tries to be like Ruby) I decided to leave them off for this project

There is even a setting in Eclipse that will automatically remove semicolons for you on save:

But the REAL power of this DTO comes in instantiation. Check out this very simple method to grab a CloudFilesConfiguration object:

protected CloudFilesConfiguration lookupConfiguration() { new CloudFilesConfiguration().with { username = BLCSystemProperty.resolveSystemProperty(CloudFilesConfiguration.USERNAME_PROP) apikey = BLCSystemProperty.resolveSystemProperty(CloudFilesConfiguration.APIKEY_PROP) container = BLCSystemProperty.resolveSystemProperty(CloudFilesConfiguration.CONTAINER_PROP) endpoint = BLCSystemProperty.resolveSystemProperty(CloudFilesConfiguration.ENDPOINT_PROP) containerSubDirectory = BLCSystemProperty.resolveSystemProperty(CloudFilesConfiguration.CONTAINER_SUBDIR_PROP) it } }

Code just simply does not get more readable than that.

with - closure that gives us an execution context to work with. In this case, everything within the with block is just like writing code within the CloudFilesConfiguration` class itself. I can set member variables without qualification

CloudFilesConfiguration` class itself. I can set member variables without qualification it - the current object contained in the with execution context. This statement just returns the newly-initialized CloudFilesConfiguration back to the caller

- the current object contained in the execution context. This statement just returns the newly-initialized back to the caller No .class - It's all implied in Groovy (finally!)

Compare it to an equivalent snippet that I'm sure plenty of Java programmers have read and/or written:

CloudFilesConfiguration config = new CloudFilesConfiguration ( ) ; config . setUsername ( BLCSystemProperty . resolveSystemProperty ( CloudFilesConfiguration . class . USERNAME_PROP ) ) ; config . setApikey ( BLCSystemProperty . resolveSystemProperty ( CloudFilesConfiguration . class . APIKEY_PROP ) ) ; config . setContainer ( BLCSystemProperty . resolveSystemProperty ( CloudFilesConfiguration . class . CONTAINER_PROP ) ) ; config . setEndpoint ( BLCSystemProperty . resolveSystemProperty ( CloudFilesConfiguration . class . ENDPOINT_PROP ) ) ; config . setContainerSubDirectory ( BLCSystemProperty . resolveSystemProperty ( CloudFilesConfiguration . class . CONTAINER_SUBDIR_PROP ) ) ; return config ;

Another closure example that I used is in a for loop ( .each ):

void addOrUpdateResources ( FileWorkArea workArea , List < File > files , boolean removeFilesFromWorkArea ) { files . each { File file - > SwiftObject obj = client . newSwiftObject ( ) obj . info . name = buildResourceName ( FilenameUtils . getName ( file . getAbsolutePath ( ) ) ) obj . setPayload ( file ) CloudFilesConfiguration conf = lookupConfiguration ( ) if ( ! client . containerExists ( conf . container ) ) { client . createContainer ( conf . container ) } client . putObject ( conf . container , obj ) client . close ( ) } }

The point of no return

You might have caught in the code snippets above that there is no return statement in the lookupConfiguration() method. That's Groovy taking another page from the Ruby book. Just like Ruby, the last statement in the function is always returned. Since the last statement in the lookupConfiguration() method is to instantiate a new CloudFilesConfiguration object, that's what gets returned to the caller.

This is in various places in the code, like the removeResource method:

boolean removeResource ( String name ) { client . removeObject ( lookupConfiguration ( ) . container , buildResourceName ( name ) ) true }

While leaving off return statements is definitely more idiomatic, I found myself occasionally including it for readability

Input/Output

Since I was writing a file provider, I had to deal with some input and output streams reading/writing from/to various file objects. Lucky for me, Groovy provides operator overloading!

SwiftObject remoteFile = client . getObject ( lookupConfiguration ( ) . container , buildResourceName ( name ) , null ) InputStream inStream = remoteFile . payload . openStream ( ) OutputStream outStream = new FileOutputStream ( localFile ) localFile . withOutputStream { out - > out < < inStream } inStream . close ( )

by wrapping the file within a withOutputStream closure, the output stream is automatically closed at the end of the execution. Within the closure, I am shifting the input stream to the output stream.

I am explicitly closing the inStream from the remote payload as it is not in an automatically-closed closure

Operator overloading is really great and is definitely one of my favorite parts of C++ (they are referred to as 'friend' functions there). If this was available in the JVM, we could transform this code:

Money amt1 = new Money ( BigDecimal . ONE ) ; Money amt2 = new Money ( BigDecimal . TWO ) ; Money sum = amt1 . add ( amt2 ) ;

into the slightly more readable:

Money amt1 = new Money ( BigDecimal . ONE ) ; Money amt2 = new Money ( BigDecimal . TWO ) ; Money sum = amt1 + amt2 ;

Java type system

I found myself using this way more than I thought I would. I figured that I would let the complier help me out as much as possible and it definitely aided in readability (especially in method parameters). Content-assist was also a problem; when I used the def keyword Eclipse didn't always know what I meant and would not always give me relevant content-assist results.

As I've gone back to this project, it looks like the def support for content-assist has gotten much better

Testing and static method mocks

There were not a whole lot of interesting results in testing with Groovy, just more of the idiomatic paradigms that I used in the file provider implementation. That said, I was really excited to mock objects with Groovy's ExpandoMetaClassand not bring in an extra mocking framework. However, the class that I needed to mock was a static method in a Broadleaf class (the BLCSystemProperty class) which is not completely instrumented by Groovy (since it is a core Java class). Because of this, it does not have the ExpandoMetaClass features and I had to instrument the mocking with PowerMock.

This turned out to be a pretty simple configuration. I annotated my test with:

@RunWith ( PowerMockRunner ) @PrepareForTest ( BLCSystemProperty ) class CloudFilesTest {

and then mocked up the systemPropertiesService method:

static def propMap = [ : ] @Before void setup ( ) { // initialize propMap and populate with property values PowerMockito . mockStatic ( BLCSystemProperty ) SystemPropertiesService propService = PowerMockito . mock ( SystemPropertiesService ) when ( propService . resolveSystemProperty ( any ( ) ) ) . thenAnswer ( new Answer ( ) { public Object answer ( InvocationOnMock invocation ) { Object [ ] args = invocation . arguments Object mock = invocation . mock propMap [ args [ 0 ] ] } } ) when ( BLCSystemProperty . systemPropertiesService ) . thenReturn ( propService ) provider . fileService = new BroadleafFileServiceImpl ( ) }

Mr. Jenkins

I was a little disappointed with the Jenkins Gradle plugin. It hasn't been updated in almost a year and it does not have feature parity with the Maven Jenkins plugin. The main feature that it is missing is the 'Perform Maven Release' functionality that we use extensively at Broadleaf.

That said, I was still able to set up a continuous build. The configuration was pretty straightforward:

These Gradle executions build the app, run cobertura reports, installs the artifacts to the local Maven repository and then uploads the artifacts to the Broadleaf nexus (both of which utilize the highly recommended Gradle Nexus plugin).

I have pretty good test coverage, if I do say so myself:

Conclusions

Writing something with Groovy and Gradle was definitely a fun venture and it was easy to see why people think it's a great improvement over core Java. Operator overloading and the with closure were definitely my favorite syntactic sugar molecules. I was really surprised at how much I found myself using the Java type system and how little I wanted to use def . If a tried-and-true strongly-typed compiler can help you write more self-documenting and bug-free code, why not use it!

Similar to the part 1 talk about Gradle, some of the Maven features were a bit lacking on Jenkins. I really wanted a release plugin that worked as well as the Maven release plugin but I'm sure one will come along eventually (or I'll write it).

Finally, Apache JClouds specifically was a bit of a pain to deal with in terms of the Rackspace API. I was able to figure out a relatively straightforward solution eventually but in general it felt a bit overarchitected. I could tell that it made some complicated stuff somewhat easier (namely, dealing with multiple providers at once) but it made some of the easy stuff astronomically more painful then they should have been.

Have you had similar experiences with Groovy and Gradle? Let us know! Updating our outdated Grails module is on the road map but we would love some help to take it to GA!