This post is about a build.xml file for Apache Ant that compiles, unit tests and packages a typical web application. The main build artifact is a timestamped WAR file.
Standardized directory layout
The build file assumes that your project uses the following directories:
- src : Java sources and classpath resources
- test : JUnit test sources and classpath resources
- web : Web resources (JSP, HTML, CSS, etc.)
- web/WEB-INF/lib : jars required by the web application at runtime
- devlib/provided : jars provided by the web container at runtime
- devlib/test : jars required for test compilation or execution
Transient build directories
The build will create these transient output directories for each stage of the build process. You should configure the version control of your project to ignore them.
- build/classes : Compiled Java code and classpath resources (compile)
- build/test-classes : Compiled JUnit tests (test-compile)
- build/test-reports : JUnit test reports (test)
- dist : WAR file (dist)
Run ant clean to delete them after you grabbed the WAR file.
The build.xml file
<project name="PROJECT_NAME" default="dist">
<property name="classes" location="build/classes"/>
<property name="test-classes" location="build/test-classes"/>
<property name="test-reports" location="build/test-reports"/>
<path id="classpath">
<fileset dir="devlib/provided">
<include name="*.jar"/>
</fileset>
<fileset dir="web/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
</path>
<path id="test-classpath">
<path refid="classpath"/>
<pathelement location="${classes}"/>
<pathelement location="${test-classes}"/>
<fileset dir="devlib/test">
<include name="*.jar"/>
</fileset>
</path>
<target name="clean">
<delete dir="dist"/>
<delete dir="build"/>
</target>
<target name="compile">
<mkdir dir="${classes}"/>
<javac destdir="${classes}">
<classpath refid="classpath"/>
<src path="src"/>
<src path="common/src"/>
</javac>
<copy todir="${classes}">
<fileset dir="src" excludes="**/*.java"/>
</copy>
</target>
<target name="test-compile" depends="compile">
<mkdir dir="${test-classes}"/>
<javac destdir="${test-classes}">
<src path="common/test"/>
<src path="test"/>
<classpath refid="test-classpath"/>
</javac>
</target>
<target name="test" depends="test-compile">
<mkdir dir="${test-reports}"/>
<junit printsummary="yes">
<classpath refid="test-classpath"/>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
<batchtest todir="${test-reports}" failureproperty="failed"
errorproperty="failed">
<fileset dir="${test-classes}" includes="**/*Test.class"/>
</batchtest>
</junit>
</target>
<tstamp>
<format property="timestamp" pattern="yyyy-MM-dd_hh-mm"/>
</tstamp>
<target name="dist" depends="clean, compile, test">
<mkdir dir="dist"/>
<war destfile="dist/${ant.project.name}_${timestamp}.war"
basedir="web"
excludes="**/CVS">
<classes dir="${classes}"/>
</war>
</target>
</project>