## 4.5 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).

### Ant Integration

When you create a Grails application via the create-app command, Grails automatically creates an Apache Ant `build.xml` file for you 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 all geared up 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 Hudson

It uses the Grails Ant task to hook into the existing Grails build system. The task allows you to 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:

Attribute | Description | Required
--- | --- | ---
home | The location of the Grails installation directory to use for the build. | Yes, unless classpath is specified.
classpathref | Classpath 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.
script | The name of the Grails script to run, e.g. "TestApp". | Yes.
args | The arguments to pass to the script, e.g. "-unit -xml". | No. Defaults to "".
environment | The Grails environment to run the script in. | No. Defaults to the script default.
includeRuntimeClasspath | Advanced 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 are using 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.

### Maven Integration

From 1.1 onwards, Grails provides integration with Maven 2 via a Maven plugin. The current Maven plugin is based on, but effectively supersedes, the version created by Octo, who did a great job.

#### Preparation

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

> The Maven 2 integration for Grails has been designed and tested for Maven 2.0.9 and above. It will not work with earlier versions.

> The default mvn setup DOES NOT supply sufficient memory to run the Grails environment. We recommend that you add the following environment variable setting to prevent poor performance:

> `export MAVEN_OPTS="-Xmx512m -XX:MaxPermSize=192m"`

#### Creating a Grails Maven Project

To create a Mavenized Grails project simply run the following command:

    mvn archetype:generate -DarchetypeGroupId=org.grails \
        -DarchetypeArtifactId=grails-maven-archetype \
        -DarchetypeVersion=1.3.2 \
        -DgroupId=example -DartifactId=my-app

Choose whichever grails version, group ID and artifact ID you want for your application, but everything else must be as written. This will create a new Maven project with a POM and a couple of other files. What you won't see is anything that looks like a Grails application. So, the next step is to create the project structure that you're used to. But first, if you want to set target JDK to Java 6, do that now. Open my-app/pom.xml and change

    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>

to

    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.6</source>
        <target>1.6</target>
      </configuration>
    </plugin>

Then you're ready to create the project structure:

    cd my-app
    mvn initialize

> if you see a message similar to this:

>     Resolving plugin JAR dependencies …
>     :: problems summary ::
>     :::: WARNINGS
>     		module not found: org.hibernate#hibernate-core;3.3.1.GA

> you need to add the plugins manually to application.properties:

>     plugins.hibernate=1.3.2
>     plugins.tomcat=1.3.2

> then run

>     mvn compile

> and the hibernate and tomcat plugins will be installed.

Now you have a Grails application all ready to go. The plugin integrates into the standard build cycle, so you can use the standard Maven phases to build and package your app: `mvn clean` , `mvn compile` , `mvn test` , `mvn package` , `mvn install` .

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

- `grails:create-controller` - Calls the create-controller command
- `grails:create-domain-class` - Calls the create-domain-class command
- `grails:create-integration-test` - Calls the create-integration-test command
- `grails:create-pom` - Creates a new Maven POM for an existing Grails project
- `grails:create-script` - Calls the create-script command
- `grails:create-service` - Calls the create-service command
- `grails:create-taglib` - Calls the create-tag-lib command
- `grails:create-unit-test` - Calls the create-unit-test command
- `grails:exec` - Executes an arbitrary Grails command line script
- `grails:generate-all` - Calls the generate-all command
- `grails:generate-controller` - Calls the generate-controller command
- `grails:generate-views` - Calls the generate-views command
- `grails:install-plugin` - Calls the install-plugin command
- `grails:install-templates` - Calls the install-templates command
- `grails:list-plugins` - Calls the list-plugins command
- `grails:package` - Calls the package command
- `grails:run-app` - Calls the run-app command
- `grails:uninstall-plugin` - Calls the uninstall-plugin command

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

#### Mavenizing an existing project

Creating a new project is great way to start, but what if you already have one? You don't want to create a new project and then copy the contents of the old one over. The solution is to create a POM for the existing project using this Maven command (substitute the version number with the grails version of your existing project):

    mvn org.grails:grails-maven-plugin:1.3.2:create-pom -DgroupId=com.mycompany

When this command has finished, you can immediately start using the standard phases, such as `mvn package`. Note that you have to specify a group ID when creating the POM.

You may also want to set target JDK to Java 6, see above.

#### 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>1.3.2</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 via the `args` property:

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

#### Debugging a Grails Maven Project

Maven can be launched in debug mode using the "mvnDebug" command. To launch your Grails application in debug, simply run:

    mvnDebug grails:run-app

The process will be suspended on startup and listening for a debugger on port 8000.

If you need more control of the debugger, this can be specified using the MAVEN_OPTS environment variable, and launch Maven via the default "mvn" command:

    MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
    mvn grails:run-app

#### Raising issues

If you come across any problems with the Maven integration, please raise a JIRA issue as a sub-task of GRAILS-3547.