Apache ANT (Another Neat Tool)
Apache Ant is a Java based build tool from Apache Software
Foundation. Apache Ant's build files are written in XML and take
advantage of the open standard, portable and easy to understand
nature of XML.
Ant is primarily used for building and deploying Java projects but
can be used for every possible repetitive tasks
Why do you need a build tool?
Do you spend your day doing the following manually?
Compile code
Package the binaries
Deploy the binaries to the test server
Test your changes
Copy code from one location to another
If you have answered yes to any of the above, then it is time to automate
the process and take away that burden from you.
On average, a developer spends 3 hours (out of a 8 hour working day)
doing mundane tasks like build and deployment. Wouldn't you be delighted
to get back the 3 hours?
Enter Apache Ant. Apache Ant is an operating system build and deployment tool that can
be executed from a command line.
Features of Apache Ant
Ant is the most complete Java build and deployment tool available.
Ant scripts are written using plain XML.
Ant is good at automating complicated repetitive tasks.
Ant comes with a big list of predefined tasks.
Ant provides an interface to develop custom tasks.
Configuring Apache Ant
Ant uses an XML file for its configuration. The default file name is build.xml. Ant
builds are based on three blocks:
 tasks, targets and extension point.
A task is a unit of work which should be performed and are small,
atomic steps, for example compile source code or create Javadoc.
Tasks can be grouped into targets.
A target can be directly invoked via Ant. Targets can specify their
dependencies. Ant will automatically execute dependent targets.
For example if target A depends on B, than Ant will first perform B
and then A.
In your build.xml file you can specify the default target. Ant will
execute this target, if no explicit target is specified.
Example,
<?xml version="1.0"?>
<project name="Hello World Project" default="info">
<target name="info">
<echo>Hello World - Welcome to Apache Ant!</echo>
</target>
</project>
All buildfiles
element.
require
the
project
element
and
at
least
one
target
The XML element project has three attributes :
Attributes
Description
name
The Name of the project. (Optional)
default
The default target for the build script. A project may
contain any number of targets. This attribute specifies
which target should be considered as the default.
(Mandatory)
basedir
The base directory (or) the root folder for the project.
(Optional)
A target is a collection of tasks that you want to run as one unit. In
our example, we have a simple target to provide an informational message
to the user.
Targets can have dependencies on other targets. For example, a deploy
target may have a dependency on the package target, and the package
target may have a dependency on the compile target and so forth.
Dependencies are denoted using the depends attribute.
For example:
<target name="deploy" depends="package">
....
</target>
<target name="pacakge" depends="clean,compile">
....
</target>
<target name="clean" >
....
</target>
<target name="compile" >
....
</target>
The target element has the following attributes:
Attributes
Description
name
The name of the target (Required)
depends
Comma separated list of all targets that this target
depends on. (Optional)
description A short description of the target. (optional)
if
Allows the execution of a target based on the trueness of a
conditional attribute. (optional)
unless
Adds the target to the dependency list of the specified
Extension Point. An Extension Point is similar to a target,
but it does not have any tasks. (Optional)
The echo task in the above example is a trivial task that prints a
message. In our example, it prints the Hello World message.
To run the ant build file, open up command prompt and navigate to the
folder where the build.xml resides, and type ant info. You could also
just type ant instead. Both will work, because info is the default target
in the build file. You should see the following output:
C:\>ant
Buildfile: C:\build.xml
info:
[echo] Hello World - Welcome to Apache Ant!
BUILD SUCCESSFUL
Total time: 0 seconds
C:\>
Property Task
Ant uses the property element which allows you to specify
properties. This allows the properties to be changed from one build
to another or from one environment to another.
By default, Ant provides the following pre-defined properties that can
be used in the build file
Properties
Description
ant.file
The full location of the build file.
ant.version
The version of the Apache Ant
installation.
basedir
The basedir of the build, as specified in
the basedir attribute of the project
element.
ant.java.version
The version of the JDK that is used by
Ant.
ant.project.name
The name of the project, as specified in
the name atrribute of the project element
ant.project.default-target
The default target of the current project
ant.project.invoked-targets
Comma separated list of the targets that
were invoked in the current project
ant.core.lib
The full location of the ant jar file
ant.home
The home directory of Ant installation
ant.library.dir
The home directory for Ant library files typically ANT_HOME/lib folder.
Ant also makes the system properties (Example: file.separator) available
to the build file.
In addition to the above, the user can define additional properties using
the property element. An example is presented below which shows how to
define a property called sitename:
<?xml version="1.0"?>
<project name="Hello World Project" default="info">
<property name="sitename" value="www.tutorialspoint.com"/>
<target name="info">
<echo>Apache Ant version is ${ant.version} - You are
at ${sitename} </echo>
</target>
</project>
Property File
The property file is named build.properties and is placed along
side the build.xml file.
You could create multiple build properties file based on the deployment
environments - such as build.properties.dev and build.properties.test
The contents of the build property file are similar to the normal
java property file.
They contain one property per line. Each property is represented by
a name and a value pair. The name and value pair are separated by
an equals sign.
It is highly recommended that the properties are annotated with
proper comments. Comments are listed using the hash character.
The following shows a build.xml and an associated build.properties file
build.xml
<?xml version="1.0"?>
<project name="Hello World Project" default="info">
<property file="build.properties"/>
<target name="info">
<echo>Apache Ant version is ${ant.version} - You are
at ${sitename} </echo>
</target>
</project>
build.properties
# The Site Name
sitename=www.tutorialspoint.com
buildversion=3.3.2
ANT Datatype
Ant provides a number of predefined data types. Do not confuse the data
types that are available in the programming language, but instead
consider the data types as set of services that are built into the
product already
The following is a list of data types provided by Apache Ant
1) File Set
The Fileset data types represents a collection of files.
The Fileset data type is usually used as a filter to include and
exclude files that match a particular pattern.
For example:
<fileset dir="${src}" casesensitive="yes">
<include name="**/*.java"/>
<exclude name="**/*Stub*"/>
</fileset>
The src attribute in the above example points to the source folder of the
project.
In the above example, the fileset selects all java files in the source
folder except those that contain the word 'Stub' in them. The
casesensitive filter is applied to the fileset which means that a file
with the name Samplestub.java will not be excluded from the fileset
2) Pattern Set
A pattern set is a pattern that allows to easily filter files or
folders based on certain patterns.
Patterns can be created using the following meta characters.
 ? - Matches one character only
 * - Matches zero or many characters
 ** - Matches zero or many directories recursively
The following example should give an idea of the usage of a pattern set.
<patternset id="java.files.without.stubs">
<include name="src/**/*.java"/>
<exclude name="src/**/*Stub*"/>
</patternset>
The patternset can then be reused with a fileset as follows:
<fileset dir="${src}" casesensitive="yes">
<patternset refid="java.files.without.stubs"/>
</fileset>
3) File List
The File list data type is similar to the file set except that the
File List contains explicitly named lists of files and do not support wild
cards
Another major difference between the file list and the file set
data type is that the file list data type can be applied for files
that may or may not exist yet.
Following is an example of the File list data type
<filelist id="config.files" dir="${webapp.src.folder}">
<file name="applicationConfig.xml"/>
<file name="faces-config.xml"/>
<file name="web.xml"/>
<file name="portlet.xml"/>
</filelist>
The webapp.src.folder attribute in the above example points to the web
application's source folder of the project.
4) Filter Set
Using a Filter Set data type with the copy task, you can replace
certain text in all files that match the pattern with a replacement
value.
A common example is to append the version number to the release notes
file, as shown in the example below
<copy todir="${output.dir}">
<fileset dir="${releasenotes.dir}" includes="**/*.txt"/>
<filterset>
<filter token="VERSION" value="${current.version}"/>
</filterset>
</copy>
The output.dir attribute in the above example points to the output folder
of the project.
The releasenotes.dir attribute in the above example points to the release
notes folder of the project.
The current.version attribute in the above example points to the current
version folder of the project.
The copy task, as the name suggests is used to copy files from one
location to another.
5) Path
The path data type is commonly used to represent a classpath.
Entries in the path are separated using a semicolon or colon.
However, these characters are replaced at run time by the running
system's path separator character.
Most commonly, the classpath is set to the list of jar files and
classes in the project, as shown in the example below:
<path id="build.classpath.jar">
<pathelement path="${env.J2EE_HOME}/${j2ee.jar}"/>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</path>
The env.J2EE_HOME attribute in the above example points to the
environment variable J2EE_HOME.
The j2ee.jar attribute in the above example points to the name of the
J2EE jar file in the J2EE base folder.
Example,
build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="wke" default="create-war" basedir=".">
<!--Define default location of build.properties -->
<property name="build.prop.file" value="build.properties" />
<!--Loading the properties -->
<property file="${build.prop.file}" />
<!--Build Artifact Locations -->
<property name="build.base.dir" value="${basedir}" />
<property name="build.lib.dir" value="${build.base.dir}/lib" />
<property name="build.config.cert.dir"
value="../web/WEB-INF/config/com/ofs/cert" />
<property name="src.core.resource.dir"
value="../src/com/wke/resource" />
<property name="src.book.cert.dir"
value="../src/com/wke/book/service" />
<property name="core.web.webinf.config.dir"
value="../web/WEB-INF/config" />
<!--<property name="thirdpary.jars" value="$
{build.base.dir}/jars" />-->
<property name="build.core.class.dir" value="$
{build.base.dir}/core/classes" />
<property name="build.core.test.dir" value="$
{build.base.dir}/core/test/classes" />
<property name="build.core.lib.dir" value="$
{build.base.dir}/core/lib" />
<!--wke jar names -->
<!--<property name="wke.core.jar.name" value="wke-core" />
<property name="wke.war.name" value="wke" />-->
<!--Build Source Locations -->
<!--<property name="src.core.dir" value="../src" />
<property name="src.edis.dir" value="../../wke.edis/src" />
<property name="web.dir" value="../web" />
<property name="test.core.dir" value="../wke.core/test" />-->
<!-- Java build options -->
<property name="javac.debug" value="true" />
<property name="javac.debug.level" value="lines,vars,source" />
<property name="javac.warn.deprecated" value="true" />
<!-- Classpath setting for thirdparty JARs -->
<path id="compile.class.path">
<fileset dir="${thirdpary.jars}">
<include name="**/*.jar" />
</fileset>
<pathelement location="${build.core.lib.dir}/$
{wke.core.jar.name}.jar" />
</path>
<!--Clean the build directory -->
<target name="clean" description="clean the directories">
<delete dir="${build.lib.dir}" />
<delete dir="${build.core.class.dir}" />
<delete dir="${build.core.test.dir}" />
<delete dir="${build.core.lib.dir}" />
</target>
<!--Prints the detail about the enviornment -->
<target name="echo-environment" description="echos the envrionment"
depends="clean">
<echo>ThirdParty Location:${thirdpary.jars}</echo>
<echo>Build Dir:${build.base.dir}</echo>
<echo>Final Product Name:${wke.war.name}</echo>
</target>
<!--Creating the build directories -->
<target name="create-build-dir" depends="echo-environment"
description="create the build dirs">
<mkdir dir="${build.lib.dir}" />
<mkdir dir="${build.core.class.dir}" />
<mkdir dir="${build.core.test.dir}" />
<mkdir dir="${build.core.lib.dir}" />
</target>
<!--Creating module jars -->
<target name="build-jar" depends="create-build-dir"
description="creates the jars">
<antcall target="core-create-jar" />
</target>
<!-- Create the Config folder and put the relevant files -->
<target name="create-config" description="creates the config">
<mkdir dir="${build.config.cert.dir}" />
<copy todir="${build.config.cert.dir}">
<fileset dir="${src.core.resource.dir}" includes="*.p12"
/>
</copy>
<copy todir="${core.web.webinf.config.dir}">
<fileset dir="${src.core.resource.dir}" includes="*.xml"
/>
<fileset dir="${src.core.resource.dir}"
includes="*.properties" />
</copy>
</target>
<!-- Creating the final war-->
<target name="create-war" depends="build-jar,create-config"
description="creates the war">
<war destfile="${build.lib.dir}/${wke.war.name}.war" webxml="$
{web.dir}/WEB-INF/web.xml">
<fileset dir="${web.dir}" />
<lib dir="${thirdpary.jars}">
<exclude name="servlet-api-2.5.jar" />
</lib>
<lib dir="${build.core.lib.dir}">
</lib>
</war>
</target>
<target name="core-create-jar" depends="core-compile">
<jar destfile="${build.core.lib.dir}/$
{wke.core.jar.name}.jar">
<fileset dir="${build.core.class.dir}" />
</jar>
</target>
<target name="core-compile">
<javac destdir="${build.core.class.dir}" deprecation="$
{javac.warn.deprecated}" debug="${javac.debug}" debuglevel="$
{javac.debug.level}" includeantruntime="no">
<classpath refid="compile.class.path" />
<src path="${src.core.dir}" />
<src path="${src.edis.dir}" />
</javac>
</target>
</project>
build.properties
#Final War Name
wke.war.name=wke
#Module jar names
wke.core.jar.name=wke-core
#Thirdparty jars location
thirdpary.jars=../build/jars
#Source code location
src.core.dir=../src
src.edis.dir=../../wke.edis/src
web.dir= ../web
#Test source code location
test.core.dir=../wke.core/test
Calling task in another xml file from main build file
<ant antfile="task_file.xml">
<!-- how do I make a task call ? -->
</ant>
task_file.xml
<project>
<target name="test_hi">
<echo message="hi" />
</target>
</project>
Using import task to call another file
<import file="ivy/ivy_build.xml"/>