Ant and Maven
Chapter 4
4.1 Introduction
Ant and Maven? Yes, it is true.
Ant isn't a language as much as it is a build tool which allows you to describe a build as a set of tasks grouped into build targets. Ant then allows you to declare dependencies between build targets. When you are using Ant you are essentially creating your own lifecycle. An Ant build.xml might have an install target which depends on a test target which depends on a compile target, but these relationships are arbitrary and managed by the person who writes the Ant build file.
Ant is something of a ancestor to Maven, it was the ubiquitous procedural build tool that almost every project used before Maven introduced the concept of wide-scale reusability of common build plugins and the concept of a universal lifecycle.
4.2. Running an Inline Ant Script in a Maven Build
4.2.1. Task
You need to run an inline Ant script as a part of your Maven build.
4.2.2. Action
Configure the run goal of the Maven AntRun plugin to execute an inline Ant script. The POM shown in configures the run goal to execute during the prepare-package phase of the build. The Ant script is contained in the tasks configuration parameter for the ant-magic execution.
Example 4.1. Executing an Inline Ant Script in a Maven Build
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sonatype.mcookbook</groupId>
<artifactId>ant-script</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>ant-script</name>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>ant-magic</id>
<phase>prepare-package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<property name="compile_classpath"
refid="maven.compile.classpath"/>
<echo file="${project.build.outputDirectory}/deps.txt"
message="compile classpath: ${compile_classpath}"/>
<copy todir="${project.build.outputDirectory}">
<fileset dir="${project.build.sourceDirectory}"/>
</copy>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
You can run this script, by executing the package phase.
[INFO] Scanning for projects...
...
[INFO] [antrun:run {execution: ant-magic}]
[INFO] Executing tasks
[copy] Copying 1 file to ~/examples/ant/ant-script/target/classes
[INFO] Executed tasks
...
[INFO] BUILD SUCCESSFUL
Once this simple Ant script has been completed, the contents of ${basedir}/target/classes/deps.txt should contain the following:
4.3. Running an External Ant Script in a Maven Build
4.3.1. Task
You need to execute an external Ant script in a Maven build.
4.3.2. Action
Configure the run goal form the Maven AntRun plugin. Define any properties you wish to pass to the external Ant build, and then call the external Ant build with the ant task, specifying the antfile and target you wish to execute.
Example 4.2. Executing an External Ant Script from a Maven Build
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
&l5;modelVersion>4.0.0&l5;/modelVersion>
&l5;groupId>org.sonatype.mcookbook&l5;/groupId>
&l5;artifactId>ant-script-ex&l5;/artifactId>
&l5;packaging>jar&l5;/packaging>
&l5;version>1.0-SNAPSHOT&l5;/version>
&l5;name>ant-script-ex&l5;/name>
&l5;build>
&l5;plugins>
&l5;plugin>
&l5;artifactId>maven-antrun-plugin&l5;/artifactId>
&l5;executions>
&l5;execution>
&l5;id>ant-magic&l5;/id>
&l5;phase>prepare-package&l5;/phase>
&l5;goals>
&l5;goal>run&l5;/goal>
&l5;/goals>
&l5;configuration>
&l5;tasks>
&l5;property name="compile_classpath" refid="maven.compile.classpath"/>
&l5;property name="outputDir" value="${project.build.outputDirectory}"/>
&l5;property name="sourceDir" value="${project.build.sourceDirectory}"/>
&l5;ant antfile="${basedir}/src/main/ant/create-deps.xml" target="create"/>
&l5;/tasks>
&l5;/configuration>
&l5;/execution>
&l5;/executions>
&l5;/plugin>
&l5;/plugins>
&l5;/build>
&l5;/project>
To execute this external Ant build, run mvn package.
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building ant-script-ex
...
[INFO] [antrun:run {execution: ant-magic}]
[INFO] Executing tasks
create:
[copy] Copying 1 file to ~/examples/ant/ant-script-ex/target/classes
[INFO] Executed tasks
...
[INFO] BUILD SUCCESSFUL
Once this simple Ant script has been completed, the contents of ${basedir}/target/classes/deps.txt should contain the following:
4.4. Creating an Ant Maven Plugin
While Maven is an improvement on Ant, Ant can still be useful when describing parts of the build process. Ant provides a set of tasks which can come in handy when you need to perform file operations or XSLT transformations or any other operation you could think of. There is a large library of available Ant tasks for everything from running JUnit tests to transforming XML to copying files to a remote server using SCP. An overview of available Ant tasks can be found online in the Apache Ant Manual. You can use these tasks as a low-level build customization language, and you can also write a Maven plugin where, instead of a Mojo written in Java, you can pass parameters to a Mojo which is an Ant build target.
4.4.1. Task
You need to write a Maven Plugin in Ant.
4.4.2. Action
To create a Maven plugin using Ant, you will need to have a pom.xml and a single Mojo implemented in Ant. To get started, create a project directory named firstant-maven-plugin. Place the following pom.xml in this directory.
Example 4.3. POM for an Ant Maven Plugin
<modelVersion>4.0.0</modelVersion>
<groupId>org.sonatype.mavenbook.plugins</groupId>
<artifactId>firstant-maven-plugin</artifactId>
<name>Example Ant Mojo - firstant-maven-plugin</name>
<packaging>maven-plugin</packaging>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-script-ant</artifactId>
<version>3.0.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.4</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-tools-ant</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
Next, you will need to create your Ant Mojo. An Ant mojo consists of two parts: the Ant tasks in an XML file, and a file which supplies Mojo descriptor information. The Ant plugin tools are going to look for both of these files in ${basedir}/src/main/scripts. One file will be named echo.build.xml and it will contain the Ant XML.
Example 4.4. Echo Ant Mojo
The other file will describe the Echo Ant Mojo and will be in the echo.mojos.xml file also in ${basedir}/src/main/scripts.
Example 4.5. Echo Ant Mojo Descriptor
<mojos>
<mojo>
<goal>echo</goal>
<call>echotarget</call>
<description>Echos a Message</description>
<parameters>
<parameter>
<name>message</name>
<property>message</property>
<required>false</required>
<expression>${message}</expression>
<type>java.lang.Object</type>
<defaultValue>Hello Maven World</defaultValue>
<description>Prints a message</description>
</parameter>
</parameters>
</mojo>
</mojos>
</pluginMetadata>
This echo.mojos.xml file configures the Mojo descriptor for this plugin. It supplies the goal name "echo", and it tells Maven what Ant task to call in the call element. In addition to configuring the description, this XML file configures the message parameter to use the expression ${message} and to have a default value of "Hello Maven World."
If you've configured your plugin groups in ~/.m2/settings.xml to include org.sonatype.mavenbook.plugins, you can install this Ant plugin by executing the following command at the command-line:
[INFO] ------------------------------------------------------------------------
[INFO] Building Example Ant Mojo - firstant-maven-plugin
[INFO] task-segment: [install]
[INFO] ------------------------------------------------------------------------
[INFO] [plugin:descriptor]
[INFO] Using 3 extractors.
[INFO] Applying extractor for language: java
[INFO] Extractor for language: java found 0 mojo descriptors.
[INFO] Applying extractor for language: bsh
[INFO] Extractor for language: bsh found 0 mojo descriptors.
[INFO] Applying extractor for language: ant
[INFO] Extractor for language: ant found 1 mojo descriptors.
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO]
Note that the plugin:descriptor goal found a single Ant mojo descriptor. To run this goal, you would execute the following command-line:
[INFO] [firstant:echo]
echotarget:
[echo] Hello Maven World
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
The echo goal executed and printed out the default value of the message parameter. If you are used to Apache Ant build scripts, you will notice that Ant prints out the name of the target executed and then adds a logging prefix to the output of the echo Ant task.
4.4.3. Detail
While Maven is an improvement on Ant, Ant can still be useful when describing parts of the build process. Ant provides a set of tasks which can come in handy when you need to perform file operations or XSLT transformations or any other operation you could think of. There is a large library of available Ant tasks for everything from running JUnit tests to transforming XML to copying files to a remote server using SCP. An overview of available Ant tasks can be found online in the Apache Ant Manual. You can use these tasks as a low-level build customization language, and you can also write a Maven plugin where, instead of a Mojo written in Java, you can pass parameters to a Mojo which is an Ant build target.