Combining Groovy and Java

Everybody refactors (I hope). But what if your standard refactoring just isn’t good enough? Take the next step in refactoring into Groovy code and see how easy it is to integrate Groovy into your existing Java projects.

The challenge

While working on a project lately, I encountered (something like) the following code:

First, this code tries to read from a URL to retrieve an XML file. Then it tries to execute some XPath queries to retrieve a NodeList, and for each item in the NodeList it adds an item to a result List. I omitted the error handling, because that would make the code example even longer.

As you might agree, the above code is quite hard to read, and gives a lot of overhead in trying to accomplish the task at hand.

While this code could probably be optimized and shorted considerably, I thought this code was ugly enough to be replaced completely. I considered my options, and I decided it would be a nice exercise for using a bit of Groovy to do the XML parsing for me, and replace the current Java code by Groovy code while maintaining the same level of functionality.

For those totally unfamiliar with Groovy, I suggest checking the Groovy website. It contains a lot of documentation and code examples. In short, Groovy is a Dynamic Scripting Language. It’s not a port, like JRuby, but has been specifically designed for working with Java.

To replace the code, I had to make sure it would:

  1. Provide the same level of functionality afterward
  2. Have less overhead
  3. Would integrate into our build system (Maven 2)

The solution

So, let’s begin at point 1. We need a bit of Groovy code to load a url, parse some XML, and build some Java objects with it. The following code does just that:

As you can see, even with the above example consisting of 50% comments, it’s still shorter and more complete than the Java version. The Groovy code is very consistent and provides almost no overhead in parsing the XML. The above example uses quite some Groovy magic, like closures, dynamic methods, shorthand method, etc.

Getting it to work

When I type the following in my favorite IDE:

And press CTRL+SHIFT+F10 (Run), it works! IntelliJ 7.0 supports Groovy (and Grails) out of the box, and does a very good job at providing a lot of the functionality Java developers are used to these days (syntax highlighting, code completion, refactoring, etc).

Integrating it with Maven

But we’re not there yet! We don’t use IntelliJ as our build, but we use Maven 2. Fortunately for us, a the beginning of December a new version of the Groovy Maven Plugin was released. This plugin makes it easy to compile Java, Groovy or a combination of both in one project. All we need to do for this is edit our Maven pom.xml to include the Groovy plugin, and change the settings.xml to include the codehaus repository.

The following lines of XML need to be added to the pom.xml:

A small explanation from the Groovy Maven Plugin:

It works by adding an extra goal execution to generate stubs during the generate-sources and generate-test-sources phases. These stubs are created from your Groovy source files and translated into minimal Java sources (containing JavaDoc, classes, fields, methods, etc. but omitting the implementation details. This allows Maven’s maven-compiler-plugin to be invoked as normal to compile Java sources and the Groovy Java stubs, thus allowing the compilation to resolve classes. After the normal Java compile, the Groovy compiler kicks in and then re-generates the real classes into places and everything is happy happy. In short: this makes sure your Java code can use the Groovy code, and vice verse.

After adding the final lines of XML to our settings (found in your home directory/.m2):

You should be all set to go. Running

should compile both your Java as well as your Groovy classes, and if everything went allright, you should see something like this in the Maven output:

Conclusion

It isn’t hard to get Groovy working in combination with your existing Java project. So download Groovy, read the docs and have a go at it!