(Quick Reference)

6.7 Ant and Maven - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari

Version: 2.4.4

6.7 Ant and Maven

If all the other projects in your team or company are built using a standard build tool such as Ant or Maven, you become the black sheep of the family when you use the Grails command line to build your application. Fortunately, you can easily integrate the Grails build system into the main build tools in use today (well, the ones in use in Java projects at least).

Maven Integration

Grails provides integration with Maven 3 with a Maven plugin.

Preparation

In order to use the Maven plugin, all you need is Maven 3 installed and set up. This is because you no longer need to install Grails separately to use it with Maven!

The Maven 3 integration for Grails has been designed and tested for Maven 3.1.0 and above. It will not work with earlier versions.

Creating a Grails Maven Project

Using the create-pom command you can generate a valid Maven pom.xml file for any existing Grails project. The below presents an example:

$ grails create-app myapp
$ cd myapp
$ grails create-pom com.mycompany

The create-pom command expects a group id as an argument. The name and the version are taken from the application.properties of the application. The Maven plugin will keep the version in the pom.xml in sync with the version in application.properties.

The following standard Maven commands are then possible:

  • compile - Compiles a Grails project
  • package - Builds a WAR file from the Grails project.
  • install - Builds a WAR file (or plugin zip/jar if a plugin) and installs it into your local Maven cache
  • test - Runs the tests of a Grails project
  • clean - Cleans the Grails project

Other standard Maven commands will likely work too.

You can also use some of the Grails commands that have been wrapped as Maven goals:

For a complete, up to date list, run mvn grails:help

Defining Plugin Dependencies

All Grails plugins are published to a standard Maven repository located at . When using the Maven plugin for Grails you must ensure that this repository is declared in your list of remote repositories:

<repository>
    <id>grails-plugins</id>
    <name>grails-plugins</name>
    <url>http://repo.grails.org/grails/plugins</url>
</repository>

With this done you can declare plugin dependencies within your pom.xml file:

<dependency>
    <groupId>org.grails.plugins</groupId>
    <artifactId>database-migration</artifactId>
    <version>1.1</version>
    <scope>runtime</scope>
    <type>zip</type>
</dependency>

Note that the type element must be set to zip.

Specifying the Grails Version to Use

The 2.4.0 version of the Maven plugin works with different versions of Grails. By default it tries to auto-detect the version of Grails to use from the grails-dependencies dependency definition found in the pom.xml:

<dependency>
    <groupId>org.grails</groupId>
    <artifactId>grails-dependencies</artifactId>
    <version>2.4.0</version>
</dependency>

If you change the version of grails-dependencies then a different version of Grails will be used. However, you can also explicitly define the Grails version to be used in the plugin configuration:

<plugin>
    <groupId>org.grails</groupId>
    <artifactId>grails-maven-plugin</artifactId>
    <version>2.4.0</version>
    <configuration>
        <grailsVersion>2.4.0</grailsVersion>
    </configuration>
    <extensions>true</extensions>
</plugin>

Debugging Grails Execution

The Maven plugin will run Grails commands in a separate process, meaning that the Grails process occupies a separate JVM as the Maven process.

To debug the Grails process you need to configure the forkDebug option in the plugin's configuration tag:

<plugin>
    <groupId>org.grails</groupId>
    <artifactId>grails-maven-plugin</artifactId>
    <version>2.4.0</version>
    <configuration>
        <forkDebug>true</forkDebug>
    </configuration>
    <extensions>true</extensions>
</plugin>

With this configuration in place the JVM executed in Maven will load in debug mode.

If you need to customize the memory of the forked process the following elements are available:

  • forkMaxMemory - The maximum amount of heap (default 1024)
  • forkMinMemory - The minimum amount of heap (default 512)
  • forkPermGen - The amount of permgen (default 256)

Multi Module Maven Builds

The Maven plugin can be used to power multi-module Grails builds. The easiest way to set this is up is with the create-multi-project-build command:

$ grails create-app myapp
$ grails create-plugin plugin1
$ grails create-plugin plugin2
$ grails create-multi-project-build org.mycompany:parent:1.0

Running mvn install will build all projects together. To enable the 'grails' command to read the POMs you can modify BuildConfig.groovy to use the POM and resolve dependencies from your Maven local cache:

grails.project.dependency.resolution = {
    …
    pom true
    repositories {
        …
        mavenLocal()    
    }
}

By reading the pom.xml file you can do an initial mvn install from the parent project to build all plugins and install them into your local maven cache and then cd into your project and use the regular grails run-app command to run your application. All previously built plugins will be resolved from the local Maven cache.

Adding Grails commands to phases

The standard POM created for you by Grails already attaches the appropriate core Grails commands to their corresponding build phases, so "compile" goes in the "compile" phase and "war" goes in the "package" phase. That doesn't help though when you want to attach a plugin's command to a particular phase. The classic example is functional tests. How do you make sure that your functional tests (using which ever plugin you have decided on) are run during the "integration-test" phase?

Fear not: all things are possible. In this case, you can associate the command to a phase using an extra "execution" block:

<plugin>
    <groupId>org.grails</groupId>
    <artifactId>grails-maven-plugin</artifactId>
    <version>2.4.0</version>
    <extensions>true</extensions>
    <executions>
        <execution>
            <goals></goals>
        </execution>
        <!-- Add the "functional-tests" command to the "integration-test" phase -->
        <execution>
            <id>functional-tests</id>
            <phase>integration-test</phase>
            <goals>
                <goal>exec</goal>
            </goals>
            <configuration>
                <command>functional-tests</command>
            </configuration>
        </execution>
    </executions>
</plugin>

This also demonstrates the grails:exec goal, which can be used to run any Grails command. Simply pass the name of the command as the command system property, and optionally specify the arguments with the args property:

mvn grails:exec -Dcommand=create-webtest -Dargs=Book

Raising issues

If you come across any problems with the Maven integration, please raise a JIRA issue.

Ant Integration

When you create a Grails application with the create-app command, Grails doesn't automatically create an Ant build.xml file but you can generate one with the integrate-with command:


grails integrate-with --ant

This creates a build.xml file containing the following targets:

  • clean - Cleans the Grails application
  • compile - Compiles your application's source code
  • test - Runs the unit tests
  • run - Equivalent to "grails run-app"
  • war - Creates a WAR file
  • deploy - Empty by default, but can be used to implement automatic deployment

Each of these can be run by Ant, for example:

ant war

The build file is configured to use Apache Ivy for dependency management, which means that it will automatically download all the requisite Grails JAR files and other dependencies on demand. You don't even have to install Grails locally to use it! That makes it particularly useful for continuous integration systems such as CruiseControl or Jenkins.

It uses the Grails Ant task to hook into the existing Grails build system. The task lets you run any Grails script that's available, not just the ones used by the generated build file. To use the task, you must first declare it:

<taskdef name="grailsTask"
         classname="grails.ant.GrailsTask"
         classpathref="grails.classpath"/>

This raises the question: what should be in "grails.classpath"? The task itself is in the "grails-bootstrap" JAR artifact, so that needs to be on the classpath at least. You should also include the "groovy-all" JAR. With the task defined, you just need to use it! The following table shows you what attributes are available:

AttributeDescriptionRequired
homeThe location of the Grails installation directory to use for the build.Yes, unless classpath is specified.
classpathrefClasspath to load Grails from. Must include the "grails-bootstrap" artifact and should include "grails-scripts".Yes, unless home is set or you use a classpath element.
scriptThe name of the Grails script to run, e.g. "TestApp".Yes.
argsThe arguments to pass to the script, e.g. "-unit -xml".No. Defaults to "".
environmentThe Grails environment to run the script in.No. Defaults to the script default.
includeRuntimeClasspathAdvanced setting: adds the application's runtime classpath to the build classpath if true.No. Defaults to true.

The task also supports the following nested elements, all of which are standard Ant path structures:

  • classpath - The build classpath (used to load Gant and the Grails scripts).
  • compileClasspath - Classpath used to compile the application's classes.
  • runtimeClasspath - Classpath used to run the application and package the WAR. Typically includes everything in @compileClasspath.
  • testClasspath - Classpath used to compile and run the tests. Typically includes everything in runtimeClasspath.

How you populate these paths is up to you. If you use the home attribute and put your own dependencies in the lib directory, then you don't even need to use any of them. For an example of their use, take a look at the generated Ant build file for new apps.