Fitting Grails into an Ant Build Environment


I’ve been working on a project that involves rolling a Grails-based application into a much larger build process, one which ties together several Java components and test suites through an Ant build process. This integration involves Ant calling the Grails command line tasks (clean, test-app, war, etc). The standard build.xml that is found after creating a new Grails application currently uses the exec task to invoke the command line tasks. While this works, it takes you out of the world of Ant (and consequently out of the world of Java).

Fortunately, for a little while now, the Grails distribution has been packaged with an Ant macro, graciously contributed by LinkedIn, which allows you to more tightly integrate Grails tasks with an Ant build. You can find the script here:

http://svn.codehaus.org/grails/trunk/grails/src/grails/grails-macros.xml

This macro sets up a Java environment using the GrailsStarter and GrailsScriptRunner bootstrap classes to startup a Grails environment and execute the given Grails Gant script. This is similar to the way the Grails command line batch/shell scripts function, however the macro does it within an Ant java task, which allows us to add additional information to the JVM as it executes, such as additional classpath information, system properties, and JVM arguments to name a few.

You can use this macro by importing it into your Ant build script and invoking it as follows (assuming your GRAILS_HOME environment variable is set properly):

<import file="${env.GRAILS_HOME}/src/grails/grails-macros.xml" />

<grails command="clean" />
<grails command="war" args="mywarfile.war"/>
...

This is certainly handy but doesn’t offer much beyond using Ant’s exec task. However, once we look at what we can pass into the macro, the added value becomes more apparent. The macro accepts several argument attributes and elements to augment the way the macro executes. The example below shows how we can add additional system properties and classpath items to a run-app command.

<grails command="run-app">
  <sysprops>
    <sysproperty key="server.port" value="9999" />
  </sysprops>
  <extend-classpath>
    <pathelement location="SOME_OTHER_LIB_LOCATION/foo.jar"/>
    <pathelement location="SOME_OTHER_LIB_LOCATION/bar.jar"/>
  </extend-classpath>
</grails>

This example shows that we can add in system properties to specify to things like the server.port value for the run-app command. In this example it is hardcoded, however in most non-trivial Ant build processes, this would be specified via properties file or some other mechanism to provide values that are specific to the build environment in question (e.g., development, test, integration, production).

What’s more interesting in this example is that we’ve added additional elements to the classpath which then get passed along to the Ant java task. This provides tremendous flexibility to include items in the classpath that do not appear in the standard Grails locations like these:

  • GRAILS_HOME\dist
  • GRAILS_HOME\lib
  • PROJECT_HOME\lib

This flexibility allows for other build artifacts in an Ant build process to be dynamically included into the Grails runtime from other locations in the build process.

It should be said that I’ve had to make some modifications to the macro in order to tailor it to my needs as well as to get it working properly across environments. You can see the changes I’ve made here.

Information and Links

Join the fray by commenting, tracking what others have to say, or linking to it from your blog.


Other Posts

Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

Be the first to leave a comment!