Chapter 4. Using Apache Ant
Introduction
Apache Ant (http://ant.apache.org/) is a Java- and XML-based automation tool that is available as open source software from the Apache Software Foundation. Ant began its life as part of the Tomcat code base. The tool’s first official release as a standalone software product was in July 2000, according to the Ant FAQ (http://ant.apache.org/faq.html). The original creator of both Ant and Tomcat is James Duncan Davidson.
Ant has evolved into the build tool of choice for automating Java software projects, which means building these projects from beginning to end. This includes compiling Java classes, creating JAR or WAR files, and initiating filesystem-related tasks such as creating directories and moving or copying files. All of these tasks are controlled by the Ant build file for a specific project.
An Ant build file is an XML file that is launched from the command line and executes Java classes behind the scenes. Ant is also extensible; you can customize this tool to suit your own purposes. In addition, Ant is cross-platform and very portable, since it is based on XML and Java. Once web developers become familiar with this handy and powerful tool, they find that it greatly eases the task of compiling, packaging, and inevitably altering and redeploying their web applications.
This chapter first describes how to download Ant and set it up on your system, and then explains Ant targets and tasks for those who are new to Ant. The rest of you can merrily move on to other recipes describing how to create a classpath that includes the necessary Tomcat JAR files, create WAR and JAR files, and use Ant to execute Tomcat’s Manager application.
4.1. Obtaining and Setting Up Ant
Solution
Point your browser to http://ant.apache.org/, download the binary or source distribution of Ant, then follow the instructions given in this recipe and on the Ant support site.
Discussion
The binary distribution of Apache Ant can be downloaded from http://ant.apache.org/bindownload.cgi. You can also download the source distribution, which contains the Java source files for Ant, from http://ant.apache.org/srcdownload.cgi. You must have the Java Software Development Kit (SDK) installed.
Tip
Ant v1.5.3 will be the last release that supports JDK 1.1. Ant v1.5.1 can run with JDK 1.1, although some tasks work only on JDK 1.2.
To use Ant, you must have a Java API for XML Processing (JAXP)-compliant XML parser available on your classpath. The binary Ant distribution includes the Apache Xerces2 XML parser. If you opt for a different JAXP-compliant parser, you should remove xercesImpl.jar and xmlParserAPIs.jar from Ant’s top-level /lib directory (as in jakarta-ant-1.5.1/lib) and put the JAR file(s) for the alternative parser into Ant’s /lib directory. You can also add them directly to your user classpath.
Tip
The user
classpath
is the
classpath
represented
by the
CLASSPATH
environment
variable
on your
machine.
This
classpath
overrides
the
default
value for
the user
classpath
(., or the
current
directory).
The
java
command-line
tool’s
-cp
or
-classpath
switches
override
the
CLASSPATH
environment
variable.
The user
classpath
can also
be set by
a JAR file
specified
by the
java
tool’s
-jar
switch.
This
designation
in turn
overrides
the other
ways of
specifying
a
classpath.
The bottom
line is
that it is
easier to
place your
parser of
choice in
the
jakarta-ant-1.5.1/lib
directory
instead of
fooling
around
with these
classpath
issues.
The complete installation directions for Ant and links to related Web pages are at http://ant.apache.org/manual/index.html.
Take the following steps to get Ant running on your machine:
Unpack the compressed file (in ZIP or TAR format) containing the Ant tool. With Ant v1.5.1, unpacking the distribution file creates a directory called jakarta-ant-1.5.1.
Set the
ANT_HOME
environment variable to the directory where you installed Ant. On Unix, this can be accomplished by typing a command-line phrase:export ANT_HOME=/usr/local/jakarta-ant-1.5.1
On Windows type:
set ANT_HOME=h:\jakarta-ant-1.5.1
Add the <Ant-installation-directory>/bin directory to your
PATH
environment variable. This allows the developer to change to any working directory with a build.xml file and typeant
to run this file (read the next recipe for a description of executing a build.xml file). The <Ant-installation-directory>/bin directory contains the scripts which launch the Java classes that form the basis of Ant.Optionally, set the
JAVA_HOME
environment variable to the directory where your JDK is installed. You might as well set theJAVA_HOME
environment variable, because the scripts that are provided with Ant in its /bin directory can then automatically add the required JDK-related classes when you want to use thejavac
orrmic
tasks. Tasks are XML elements that do certain jobs in Ant files, such aswar
(to create Web Archive files) andjavac
(to compile Java classes with Ant).Test your installation by typing
ant -version
. If everything goes well, this command produces a return value like this:K:\>ant -version Apache Ant version 1.5.1 compiled on October 2 2002
See Also
Recipe 4.2 on using Ant targets; Recipe 4.3 on including Tomcat JAR files in the Ant classpath; Recipe 4.4 on compiling a servlet with Ant; Recipe 4.5 on creating a WAR file with Ant; Recipe 4.6 on using Ant to create JAR files; Recipe 4.7 and Recipe 4.8 on starting and stopping Tomcat with Ant; Recipe 2.1 and Recipe 2.6 on deploying web applications using Ant; the Apache Ant manual: http://ant.apache.org/manual/index.html; the Apache Ant Project: http://ant.apache.org.
4.2. Using Ant Targets
Solution
Create one or more target
elements as child
elements of a project
element. Make sure the
target
s
have the required
name
attribute and
value.
Discussion
An Ant build file is an XML
file—in other words, a
plaintext file that
includes elements and
attributes. Example
4-1
shows an Ant file that
echoes a message to the
console. As mentioned in
the introduction, Ant
files execute Java code
behind the scenes. The
way you control the
desired actions of your
build file is by
arranging one or more
target
elements inside the
project
root element.
<project name="Cookbook" default="echo-message" basedir="."><target name="echo-message"
description="Echoing a message to the console">
<echo message="Hello from the first Ant file"/>
</target>
</project>
Ant files have one project
root element, which must
have a default
attribute and value. The
default
attribute specifies the
target that runs if no
other targets are
identified on the command
line. The name
and basedir
attributes are optional.
The name
attribute, as you might
have guessed, gives the
project
element a descriptive
name. The basedir
attribute specifies the
directory by which paths
that are referred to in
the file are calculated.
Its default value is the
directory containing the
build file.
What are targets? They are groups
of tasks,
represented in Ant by a
target
element. Targets group
one or more tasks (which
are in turn represented
by a task
element) into logical and
named units of control,
similar to Java methods.
Tasks include actions that compile
Java files (the javac
task), copy
files from one location
to another (copy
),
and create JAR or WAR
files (aptly named
jar
and war
).
For instance, the
echo-message
target
in Example
4-1
calls the echo
task.
The target’s name in Example
4-1
is echo-message
,
which is just a name that
I created for it. A
target’s description
attribute is optional, as
are three other
attributes: depends
,
if
,
and unless
.
I’ll explain the purpose
of depends
shortly; the if
and unless
attributes allow the
conditional execution of
targets.
As long as Ant is properly set up on your computer, here is what the command-line sequence for executing this example build.xml file might look like:
H:\book\cookbook\sec1\sec1_3>ant Buildfile: build.xml echo-message: [echo] Hello from the first Ant file. BUILD SUCCESSFUL Total time: 3 seconds
First, the XML file with the
project
root element is saved
with the filename
build.xml.
Then the user changes to
the directory that
contains this file and
types ant
,
without any options. Ant
then looks for a file
called
build.xml
in the current directory
and runs the project’s
default target (in Example
4-1,
the echo-message
target).
Note
You can give the
build
file a
name other
than
build.xml,
but then
you need
to run Ant
with the
-buildfile
option:
ant -buildfile dev.xml
Most
build files involve
several targets that
execute in a certain
sequence to initiate Java
development tasks. Example
4-2
demonstrates the depends
attribute. This example
shows how to execute
several targets in a
specified
sequence.
<project name="Cookbook" default="echo-message" basedir="."> <target name="init"> <property name="name" value="Bruce Perry"/> </target> <target name="show-props" depends="init"> <echo message= "The 'name' property value is: ${name}"/> <echo message= "OS name and version is: ${os.name} ${os.version} "/> <echo message= "Your Java home is: ${java.home} "/> </target> <target name="echo-message" depends="show-props"> <echo message= "Hello from the first Ant file in directory: ${basedir}"/> </target> </project>
This time, instead of just one
target, the project
element has several
nested targets. The
echo-message
target is still the
default target, but its
behavior has changed due
to the value of its
depends
attribute. This optional
attribute specifies the
name of one or more Ant
targets that must be
executed prior to the
current target. In other
words, the echo-message
target specifies, “I
depend on the show-props
target, so execute it
before me.” The show-props
target, however, also has
a depends
attribute that indicates
a reliance on the
init
target. As a result, this
build file establishes a
sequence for executing
its targets: init
→
show-props
→
echo-message
.
The result of running the prior build file at the command line is shown here:
H:\book\cookbook\sec1\sec1_3>ant Buildfile: build.xml init: show-props: [echo] The 'name' property value is: Bruce Perry [echo] OS name and version is: Windows NT 4.0 [echo] Your Java home is: h:\jdk1.3.1_02\jre echo-message: [echo] Hello from the first Ant file in directory: H:\book\cookbook\sec1\sec1_3 BUILD SUCCESSFUL Total time: 2 seconds
Here is what this build file accomplishes:
The
init
target first creates aname
property that contains the value “Bruce Perry”. The target uses theproperty
task to accomplish this. Recall that tasks do the real work in Ant; targets are simply grouping elements that call one or more tasks.The
show-props
target then echoes the values of thename
property (created by theinit
target) and three built-in properties:os.name
,os.version
, andjava.home
.The
echo-message
target issues its message to the console and returns the value of thebasedir
property. All of the targets use theecho
task to deliver their messages.
Note that the name
property would not be set
if the init
target was never
executed. If the show-props
target is defined as seen
here, there will be
problems:
<target name="show-props"> . . . </target>
However, it is properly defined as follows:
<target name="show-props" depends="init"> . . . </target>
Without the depends
attribute, the init
target would never be
executed, because the
build file’s execution
sequence would look like
show-props
→
echo-message
.
The name
property would never be
given a value.
Ant build files are usually much more complex than these examples, which is more of a testament to Ant’s power than evidence of poor design. Chapter 2 shows how to deploy individual servlets and web applications with more extensive Ant files.
See Also
Recipe
4.1
on downloading and
setting up Ant; Recipe
4.3
on including Tomcat JAR
files in the Ant
classpath; Recipe
4.4
on compiling a servlet
with Ant; Recipe
4.5
on creating a JAR file
with Ant; Recipe
4.7
and Recipe
4.8
on starting and stopping
Tomcat with Ant; Recipe
2.1
and Recipe
2.6
on deploying web
applications using Ant;
the Ant manual section on
the property
task: http://ant.apache.org/manual/CoreTasks/property.html;
the Ant manual segment on
targets
:
http://ant.apache.org/manual/using.html#targets;
the Apache Ant manual
index page: http://ant.apache.org/manual/index.html;
the Apache Ant Project:
http://ant.apache.org
.
4.3. Including Tomcat JAR files in the Build File Classpath
Solution
Use a path-like structure to define the classpath, then refer to this classpath whenever you need it. Specify the directories where the necessary JAR files are located with an external properties file.
Discussion
Before you can compile a servlet using Ant, you must ensure that the servlet API classes are available on the classpath that the Ant build file is using for compilation. For example, the <Tomcat-installation-directory>/common/lib directory contains servlet.jar, which includes the necessary classes for compiling a servlet. In addition, you might want to include the mail.jar component from the same directory to compile a servlet that uses the JavaMail API. A different directory—<Tomcat-installation-directory>/common/endorsed—includes the xmlParserAPIs.jar file, which you might specify on the classpath to use the associated SAX and DOM XML programming classes.
Example
4-3
defines a classpath using
a path
XML element. A compile-servlet
target further down in
the XML file then uses
the defined classpath to
compile a servlet.
<project name="Cookbook" default="compile-servlet" basedir="."> <!-- include compiled-servlet and tomcat-dir properties --> <property file="global.properties" /><path id="servlet-classpath"> <fileset dir="${tomcat.dir}/common/lib"> <include name="*.jar" /> </fileset> <fileset dir="${tomcat.dir}/common/endorsed"> <include name="*.jar" /> </fileset> </path> <target name="compile-servlet"> <echo message="Compiling the servlet...."/> <javac srcdir="${src}" destdir="${build}"> <include name="${compiled.servlet}.java" /> <classpath refid="servlet-classpath"/> </javac> </target> </project>
Using the path
element, the classpath
can be defined similarly
to an instance variable
of a Java class, and its
value can then be used
throughout the build
file. The advantage of
this approach is that the
classpath may be very
complex, but it has to be
defined only once.
Whenever there is a need
for a classpath in an Ant
file, the classpath
element and its refid
attribute can be used to
pull in the defined
classpath. In Example
4-3,
the path element is given
a unique ID,
“servlet-classpath.” The
developer creates this
name to uniquely identify
the path-like structure.
Another
core type of Ant task is
a fileset
.
fileset
s
are elements that
represent groups of
files. The two nested
fileset
s
in the example have
dir
attributes that specify
two directories under the
Tomcat installation
directory:
./common/lib
and
./common/endorsed.
These are directories
that contain many
important Java libraries,
such as
servlet.jar
and
mail.jar.
A fileset
element’s nested include
element creates a pattern
(with the name
attribute) that specifies
the types of files to
include in each fileset
.
The example includes all
files in the specified
directories ending in
“.jar”.
If you wanted to further refine
the types of JAR files
that are included in a
fileset, you could use
the fileset
’s
nested exclude
element:
<fileset dir="${tomcat.dir}/common/lib"> <include name="*.jar" /> <exclude name="commons*.jar"/> </fileset>
The pattern “commons*.jar” excludes all the JAR files from the classpath that begin with the word “commons,” followed by zero or more characters and a “.jar” suffix.
The compile.servlet
target in Example
4-3
echoes a message to the
console, then uses the
javac
task to compile a
servlet.
This code from Example 4-3 makes two properties that are defined in another file available to the Ant build file:
<property file="global.properties" />
Here is what the global.properties file looks like:
tomcat.dir=k:/jakarta-tomcat-4.1.12 compiled.servlet=MyTask src=.\src build=.\build
The property compiled.servlet
evaluates to the name of
the Java source file that
is being compiled. The
tomcat.dir
file is the file path to
the Tomcat root
directory.
In Example
4-3,
the classpath
element is nested inside
the javac
task, as in:
<javac srcdir="${src}" destdir="${build}"> <include name="${compiled.servlet}.java" /> <classpath refid="servlet-classpath"/> </javac>
The classpath
element’s refid
attribute pulls in the
classpath that was
defined earlier in the
build file (including all
the Tomcat JARs in
./common/lib
and
./common/endorsed).
The value of the refid
attribute is the id
of the path
element
(“servlet-classpath”). In
other words, the path
element in Example
4-3
represents a classpath;
the element’s id
or name is
“servlet-classpath.”
If it is necessary to add more
classes or JARs to the
classpath that you are
defining in an Ant file,
then add another nested
fileset
to the path
element. Example
4-4
adds all of the contents
of the
build
directory to the
classpath defined by
Example
4-3
(along with the
Tomcat-related JARs) by
adding a third nested
fileset
.
<path id="servlet-classpath">
<fileset dir="${tomcat.dir}/common/lib">
<include name="*.jar" />
</fileset>
<fileset dir="${tomcat.dir}/common/endorsed">
<include name="*.jar" />
</fileset><fileset dir="./build"/>
</path>
Note
An idiom that often
appears in
path-related
patterns
is
**
,
which
means zero
or more
directories.
For
example,
the
following
fileset
tag
includes
all of the
files
contained
in any
nested
images
folders
(src
is a
property
name
pointing
to the
source
directory
of this
fileset
),
no matter
how deeply
they are
nested:
<fileset dir="${src}"> <include name="**/images/*"/> </fileset>
See Also
Recipe
4.1
on downloading and
setting up Ant; Recipe
4.2
on writing Ant targets;
Recipe
4.4
on compiling a servlet
with Ant; Recipe
4.5
on creating a WAR file
with Ant; Recipe
4.6
on using Ant to create
JAR files; Recipe
4.7
and Recipe
4.8
on starting and stopping
Tomcat with Ant; Recipe
2.1
and Recipe
2.6
on deploying web
applications using Ant;
the Ant manual section on
the property
task: http://ant.apache.org/manual/CoreTasks/property.html;
the Ant manual segment on
target
s:
http://ant.apache.org/manual/using.html#targets;
the Apache Ant manual
index page: http://ant.apache.org/manual/index.html;
the Apache Ant Project:
http://ant.apache.org.
4.4. Compiling a Servlet with an Ant Build File
Problem
You want to set up a simple build file that you can use to compile individual servlets, without hardcoding servlet names.
Solution
Design a build file so that the name of the Java class to compile can be set from an external properties file or from the command line.
Discussion
If you are not using an IDE to develop and compile your servlets, an Ant build file can automate the compiling of your source files. In order to make this build file reusable, you should design it to get the name of the file from an external properties file or from the command line.
Ant’s advantages come to the fore when it is used to automate all of the aspects of building, archiving, and deploying a web application. However, you can also use Ant as a kind of batch processor. In this recipe, I use Ant to dynamically choose a Java file to compile.
The build.xml
file in Example
4-5
imports a couple of
properties from a
build.properties
file, including the name
of the servlet to be
compiled. One way to
choose a different Java
file to compile is to
change the value of the
compiled.servlet
property in this file,
without touching the
build file:
tomcat.dir=/users/bruceper/java/jakarta-tomcat-4.1.12 compiled.servlet=MyServlet
To run Example
4-5,
change to the directory
where the build.xml
file is located and type
ant
without any options.
Note
If you are running an Ant build file with a different name, then launch it with this command line:
ant -buildfile ant_compiler.xml
First, this file imports the
tomcat.dir
and compiled.servlet
properties from a
build.properties
file. This file is
located in the same
directory as the build
file. The tomcat.dir
property is used to
create a classpath
composed of the JAR files
in two directories that
are a part of Tomcat’s
directory tree (see Recipe
4.2).
<project name="servlet compiler" default="compile" basedir="."> <property file="build.properties" /><path id="servlet-classpath"> <fileset dir="${tomcat.dir}/common/lib"> <include name="*.jar" /> </fileset> <fileset dir="${tomcat.dir}/common/endorsed"> <include name="*.jar" /> </fileset> </path> <target name="init" description="Initializes some properties."> <echo message="Initializing properties."/> <property name="build" value="./build" /> <property name="src" value="./src" /> </target> <target name="prepare" depends="init"> <echo message="Cleaning up the build directory."/> <delete dir="${build}"/> <mkdir dir="${build}"/> </target> <target name="compile" depends="prepare" description="Compile the servlet"> <echo message="Compiling the Java file "/> <echo message="${compiled.servlet}.java..."/> <javac srcdir="${src}" destdir="${build}"> <include name="${compiled.servlet}.java" /> <classpath refid="servlet-classpath "/> </javac> </target> </project>
The init
target
creates two properties
representing the source
(src
)
and destination (build
)
directories of the target
servlet. The Java file
waiting to be compiled is
located in an src
directory. A typical
build file also has an
init
target that initializes
several more properties.
Since the compile
target has a depends
attribute that specifies
the prepare
target, and the prepare
target depends on
init
,
then the build sequence
looks like init
→
prepare
→
compile
.
The prepare
target just cleans up the
build
directory to ensure that
the
build
directory contains the
latest compiled classes.
The compile
target uses the javac
task to actually compile
the Java file. javac
has attributes that
specify the source and
destination directories
of the Java file(s) that
it will attempt to
compile. Example
4-5
uses the src
and build
properties to provide
values for these
attributes. Two nested
elements of the javac
task compile the
specified servlet file
and provide the classpath
that the javac
task uses (see Recipe
4.2).
Here is the console output after running this build file (with some editing for readability):
init: [echo] Initializing properties. prepare: [echo] Cleaning up the build directory. [delete] Deleting directory /Users/bruceper/books/cookbook/sec1/sec1_3/build [mkdir] Created dir: /Users/bruceper/books/cookbook/sec1/sec1_3/build compile: [echo] Compiling the Java file MyServlet.java... [javac] Compiling 1 source file to /Users/bruceper/books/cookbook/sec1/sec1_3/build BUILD SUCCESSFUL Total time: 6 seconds
Using the command line to declare the target servlet
What if you want to
change the
servlet
that you
are
compiling,
but are
not
inclined
to type
the new
Java
filename
into the
build.properties
file?
Running
the
build.xml
Ant file
from the
command
line in
the
following
manner
will
override
the
imported
compiled.servlet
property:
ant -Dcompiled.servlet=AnotherServlet
AnotherServlet.java is the filename in this example of the Java file that awaits compilation in the src directory. This fragment of output shows that any properties passed in from the command line override properties of the same name created within or imported into the build file:
compile: [echo] Compiling the Java file AnotherServlet.java... [javac] Compiling 1 source file to /Users/bruceper/books/cookbook/sec1/sec1_3/build
The javac
task
compiles
only only
the java
files in
the
src
directory
that do
not have a
corresponding
class
file, or
in cases
where the
class file
is older
than its
corresponding
.java
file. As
always,
check the
Ant manual
to find
out about
all the
different
variations
and
attributes
of
javac
:
http://ant.apache.org/manual/CoreTasks/javac.html.
Note
If
you
want
to
copy
the
compiled
servlet
class
to
a
web
application
directory,
you
could
add
a
deploy-servlet
target
that
uses
the
copy
Ant
task:
<target name="deploy-servlet" depends="compile"> <echo message= "Copying the servlet to Tomcat web app"/> <copy todir="${tomcat.webapps}/WEB-INF/classes"> <fileset dir="${build}" /> </copy> </target>
The
copy
task
takes
its
nested
fileset
,
which
represents
the
contents
of
the
directory
named
by
the
build
property
value,
and
copies
these
class
files
to
the
WEB-INF/classes
directory
of
Tomcat’s
default
web
application.
See Also
Recipe
4.1
on downloading and
setting up Ant; Recipe
4.2
on writing Ant targets;
Recipe
4.3
on creating a classpath
for an Ant file; Recipe
4.5
on creating a WAR file
with Ant; Recipe
4.6
on using Ant to create
JAR files; Recipe
4.7
and Recipe
4.8
on starting and stopping
Tomcat with Ant; Recipe
2.1
and Recipe
2.6
on deploying web
applications using Ant;
the Ant manual section on
the property
task: http://ant.apache.org/manual/CoreTasks/property.html;
the Ant manual segment on
targets
:
http://ant.apache.org/manual/using.html#targets;
the Apache Ant manual
index page: http://ant.apache.org/manual/index.html;
the Apache Ant Project,
http://ant.apache.org.
4.5. Creating a WAR File with Ant
Discussion
A WAR file is a web application
archive that contains
servlet classes, JSP
files, HTML files, image
directories, JAR files,
XML configuration files,
and other resources that
a web application depends
on. The WAR is deployed
on a web container like
Tomcat in order to make
the web application
available to the
container’s users. Ant
includes a war
task that makes it easy
to generate a WAR from a
directory structure that
contains the necessary
web application files.
Example 4-6 is a standalone build file that creates a WAR file. It could easily comprise one target in a complex build file that compiles Java files, creates the WAR, and deploys the application (see Recipe 2.6).
This example creates a build
sequence of init
→
prepare
→
create-war
.
The init
target creates several
properties that refer to
directories, such as the
build
directory containing the
servlet class files. The
context-path
property provides the
context path for the web
application, and in this
case, the name of the WAR
file
(myapp.war).
You execute this build file from a command prompt whose working directory is the web application’s root or top-level directory.
<project name="war-task" default="create-war" basedir=".">
<target name="init"
description="Initializes some properties.">
<echo message="Initializing properties."/>
<property name="build" value=".\build" />
<property name="src" value=".\src" />
<property name="dist" value=".\dist" />
<property name="lib" value=".\lib" />
<property name="web" value=".\web" />
<property name="meta" value=".\meta" />
<property name="context-path" value="myapp" />
</target>
<target name="prepare" depends="init">
<echo message=
"Cleaning up the build and dist directories."/>
<delete dir="${build}"/>
<mkdir dir="${build}"/>
<delete dir="${dist}"/>
<mkdir dir="${dist}"/>
</target><target name="create-war" description=
"creates a web application archive file"
depends="prepare">
<war destfile="${dist}/${context-path}.war"
webxml="${meta}/web.xml">
<classes dir="${build}"/>
<lib dir="${lib}"/>
<fileset dir="${web}"/>
</war>
</target>
</project>
If the build file was called war-task.xml, then the Ant file is executed with this command line:
ant -buildfile war-task.xml
The create-war
target calls the war
task.
The war
task’s
destfile
attribute is required; it
specifies the location of
the resulting WAR file.
Example
4-6
creates the WAR in the
dist
directory. The webxml
attribute specifies the
location of the web
application’s deployment
descriptor. This web
application’s
web.xml
file (in this example) is
located in the
meta
directory.
The example war
task has three nested
elements: classes
,
lib
,
and fileset
.
The dir
attribute of the classes
element points to the
directory that contains
the Java classes that are
located in the
WEB-INF/classes
directory. The war
task automatically
creates the
WEB-INF/classes
directory in the WAR
file. This task also
reproduces all the
package-related
directories in the
build
directory when it creates
WEB-INF/classes.
In other words, if the
build
directory includes a
com/jspservletcookbook
directory structure, then
the WAR will have the
same structure in
WEB-INF/classes.
The lib
element
grabs and stores any JAR
files that will be
located in the WAR file’s
WEB-INF/lib
directory. Finally, the
fileset
nested element, in this
case, pulls in all the
static files and any
nested
image
directories that are
contained in
/web
and places them at the
top level of the WAR’s
directory tree. Here is
what the output of this
build file looks like
(with some editing for
readability):
init: [echo] Initializing properties. prepare: [echo] Cleaning up the build and dist directories. [delete] Deleting directory /Users/bruceper/books/cookbook/build [mkdir] Created dir: /Users/bruceper/books/cookbook/build [delete] Deleting directory /Users/bruceper/books/cookbook/dist [mkdir] Created dir: /Users/bruceper/books/cookbook/dist create-war: [war] Building war: /Users/bruceper/books/cookbook/dist/myapp.war
The war
task has
numerous other optional
attributes that are
explained in the Ant
manual at http://ant.apache.org/manual/CoreTasks/war.html.
See Also
Recipe
4.1
on downloading and
setting up Ant; Recipe
4.2
on writing Ant targets;
Recipe
4.3
on creating a classpath
for an Ant file; Recipe
4.4
on compiling a servlet
with Ant; Recipe
4.6
on using Ant to create
JAR files; Recipe
4.7
and Recipe
4.8
on starting and stopping
Tomcat with Ant; Recipe
2.1
and Recipe
2.6
on deploying web
applications using Ant;
the Ant manual section on
the property
task: http://ant.apache.org/manual/CoreTasks/property.html;
the Ant manual segment on
targets
:
http://ant.apache.org/manual/using.html#targets;
the Apache Ant manual
index page: http://ant.apache.org/manual/index.html;
the Apache Ant Project:
http://ant.apache.org.
4.6. Creating a JAR File with Ant
Solution
Use the built-in jar
task.
Discussion
The jar
task automates the
creation of JAR files.
Like the war
task for WARs, the
jar
task allows you to
automate the command-line
phrases you would have to
type in for creating
JARs. In this way, build
files using the jar
task are somewhat like
shell scripts or batch
files for creating JARs.
The
Sun
Microsystems JAR file
specification can be
found at http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html.
In
web applications, JAR
files are used to contain
separate code libraries
that the web application
depends on, such as a
database driver. They are
located in a web
application’s
WEB-INF/lib
directory. Example
4-7
shows an Ant target that
uses the jar
task to create a JAR, and
then copies the JAR file
to the
lib
directory of a web
application. These
actions precede the
archiving of the web
application into a WAR
file, which can be
included in the same
build file to automate
everything at once (see
Recipe
4.5
on creating WAR files).
<project name="jar-task" default="create-jar" basedir=".">
<target name="init"
description="Initializes some properties.">
<echo message="Initializing properties."/>
<property name="dist" value="dist" />
<property name="web" value="web" />
<property name="meta" value="meta" />
<property name="jar-name" value="myutils" />
</target>
<target name="prepare" depends="init">
<echo message=
"Cleaning up the build and dist directories."/>
<delete dir="${dist}"/>
<mkdir dir="${dist}"/>
</target><target name="create-jar"
description="creates a JAR archive file"
depends="prepare">
<jar destfile="${dist}/${jar-name}.jar"
basedir="../../"
includes="**/*.class **/${web}/*.html">
<fileset dir="../../images"/>
</jar>
</target>
</project>
This build file contains three
targets in the build
sequence init
→
prepare
→
create-jar
.
These targets create some
properties and clean up a
directory called
dist
that contains the
resultant JAR file. The
create-jar
target calls the jar
task, which looks like:
<jar destfile="${dist}/${jar-name}.jar" basedir="../../" includes="**/*.class **/${web}/*.html"> <fileset dir="../../images"/> </jar>
The destfile
attribute of the jar
element specifies the
location and name of the
JAR file after it is
created. I used a
property called jar-name
here, so that the user
can run this Ant file
from the command line and
feed a new JAR filename
into the build file if
need be, as in:
ant -Djar-name=mynewjar.jar
Tip
Remember that any
properties
specified
with the
-D
switch
override
the
properties
of the
same name
defined
inside the
build
file.
The basedir
attribute of the jar
task identifies the
top-level directory of
files that will be
included in the JAR. In
the example, the pattern
../../
means “go up two
directories from the
basedir
of this project”; in
other words, go up two
directories from where
the Ant build file is
located.
The includes
attribute has two
space-separated patterns
(you can also separate
them with a comma). The
patterns further refine
the types of files that
will be included in the
JAR file. The first
pattern specifies the
inclusion of all the
files ending with the
.class
suffix that are located
in zero or more
directories beneath the
basedir
location. This JAR, as a
result, contains all of
the Java class files in
all directories nested
beneath the base
directory; the JAR
reproduces any nested
directories that it finds
with the class files. The
other pattern (**/${web}/*.html
)
takes all directories
nested beneath the base
directory called
web
and includes any files
that end with
.html
in the JAR. Once again,
the nested directories
will be included with the
JAR and the HTML files.
Finally, a fileset
element nested within the
jar
task grabs all the
contents of the
../../images
folder and includes them
in the JAR, but
it does
not
include
the images
folder
itself.
A way to include the
images
folder and its contents
at the top level of the
JAR is to change the
jar
task to:
<jar destfile="${dist}/${jar-name}.jar" basedir="../../"
includes="**/*.class **/${web}/*.html**/images/*.gif"/>
This task adds a third pattern to
the includes
attribute
(**/images/*.gif
),
which grabs all the GIF
files contained by any
images
directories that are
nested in the base
directory (the value of
the jar
element’s basedir
attribute). An
images
directory will be
included in the JAR if
one is found.
Manifest
The jar
task
creates a
META-INF/MANIFEST.MF
file for
the JAR if
the
jar
task’s
manifest
attribute
does not
appear.
The
default
manifest
looks like
this:
Manifest-Version: 1.0 Created-By: Apache Ant 1.5.1
If you want to
specify
the
location
of your
own
manifest
file for
reasons
such as
signing a
JAR file
or
specifying
the file
that
contains
the
main(
)
method in
an
executable
JAR, use
the
jar
task’s
manifest
attribute.
This
optional
attribute
can be
either the
file
location
of the
manifest
or the
name of
another
JAR that
has been
added by
using a
nested
fileset
element.
If it is a
JAR, the
task looks
in that
JAR for
the
META-INF/MANIFEST.MF
manifest.
See Also
Recipe
4.1
on downloading and
setting up Ant; Recipe
4.2
on writing Ant targets;
Recipe
4.3
on creating a classpath
for an Ant file; Recipe
4.4
on compiling a servlet
with Ant; Recipe
4.7
and Recipe
4.8
on starting and stopping
Tomcat with Ant; Recipe
2.1
and Recipe
2.6
on deploying web
applications using Ant;
the Ant manual section on
the property
task: http://ant.apache.org/manual/CoreTasks/property.html;
the Ant manual segment on
targets
:
http://ant.apache.org/manual/using.html#targets;
the Apache Ant manual
index page: http://ant.apache.org/manual/index.html;
the Apache Ant Project: http://ant.apache.org.
4.7. Starting a Tomcat Application with Ant
Discussion
The Tomcat servlet and JSP container includes a built-in web application called "Manager” that you can use to start, stop, deploy, and initiate other administrative tasks with web applications. Tomcat makes this application available from the /manager context path.
Tomcat Version 4 (and later) includes Java classes that allow developers to use the Manager application from their Ant build files. The advantage of using the Manager application from Ant is that you do not have to configure the conf/server.xml file to make the web application dynamically reloadable (see Recipe 2.2). In addition, you can start or stop a single web application without disrupting other Tomcat applications.
Tip
The Manager documentation is found online at http://jakarta.apache.org/tomcat/tomcat-4.1-doc/printer/manager-howto.html
Take these steps to start Tomcat from Ant:
Make sure you have the necessary JAR file required to use the Ant
task
for starting Tomcat: <Ant-installation-directory>/lib/catalina-ant.jar. Copy this JAR from the <Tomcat-installation-directory>/server/lib directory to your <Ant-installation-directory>/lib directory (otherwise known as ANT_HOME/lib).Make sure the Tomcat user database includes a username that is linked to the manager role. Only administrative users should be authorized to start and stop web applications using the Manager tool. The conf/tomcat-users.xml file maps users and passwords to roles. A user has to be mapped to the manager role to be able to use the Manager tool. Here is an example of one of these user mappings in tomcat-users.xml:
<user username="doug" password= "_1968dgw" roles="manager,dbadmin"/>
Use the
taskdef
element in the Ant file to define the custom task and give it a name. Example 4-8 gives the task the namestart
, which is used by the target that is responsible for starting Tomcat.Run the Ant file at the command line by changing to its directory and typing
ant
.
Example
4-8
shows the taskdef
element that defines the
start task, followed by
the target that starts
the specified Tomcat
application.
<project name="My Project" default="start-tomcat" basedir="."><taskdef name="start" classname="org.apache.catalina.ant.StartTask" />
<!-- import properties specifying username, password, url, and context-path -->
<property file="global.properties" />
<target name="start-tomcat"
description="Starts the Web application">
<echo message="Starting the default application ${ context-path}..."/>
<start
url="${url}"
username="${username}"
password="${password}"
path="/${context-path}" />
</target>
</project>
The start
task has
four attributes that
Example
4-8
sets using a global.properties
file. This is a text file
containing four
name/value pairs, which
are imported into the Ant
file using the property
task:
<property file="global.properties" />
The global.properties file is located in the same directory as the Ant build file. Here are the contents of the global.properties file:
url=http://localhost:8080/manager username=bruce password=bruce1957 context-path=home
The url
property
specifies the Tomcat
Manager URL, the username
and password
identify the user who is
mapped in the Tomcat user
database to the
manager
role, the context-path
property specifies the
context path of the web
application you are
starting, and the Ant
file itself specifies the
opening slash (/)
character for the context
path.
Note
Another way to pass properties to an Ant file is on the command line:
ant -Dusername=bruce -Dpassword=bruce1957 -Durl=http://localhost:8080/manager -Dcontext-path=home
Properties added on
the
command
line
override
those
specified
by the
property
task.
Launch this Ant file by changing
to its directory at the
command line and typing
ant
or ant
-buildfile
buildfile-name
.
Here is the command-line
output:
H:\book\cookbook\code\chap4>ant -buildfile start.xml
Buildfile: start.xml
start-tomcat:
[echo] Starting the default application home...
[start] OK - Started application at context path /home
BUILD SUCCESSFUL
Total time: 4 seconds
If an application is stopped, it is unavailable to web users (see Recipe 4.8). When the application is started again, it can receive requests normally.
Tip
The Tomcat manager application can initiate many other common administrative tasks such as deploying applications (see Recipe 2.6).
See Also
The Tomcat Manager application
description: http://jakarta.apache.org/tomcat/tomcat-4.1-doc/manager-howto.html;
Recipe
4.1
on downloading and
setting up Ant; Recipe
4.2
on writing Ant targets;
Recipe
4.3
on creating a classpath
for an Ant file; Recipe
4.4
on compiling a servlet
with Ant; Recipe
4.5
and Recipe
4.6
on creating WAR and JAR
files; Recipe
4.8
on stopping Tomcat with
Ant; Recipe
2.1
and Recipe
2.6
on deploying web
applications using Ant;
the Ant manual section on
the property
task: http://ant.apache.org/manual/CoreTasks/property.html;
the Ant manual segment on
targets
:
http://ant.apache.org/manual/using.html#targets;
the Apache Ant manual
index page: http://ant.apache.org/manual/index.html;
the Apache Ant Project:
http://ant.apache.org.
4.8. Stopping a Tomcat Application with Ant
Solution
Define a task
in the Ant file using a
taskdef
element and the Java
class org.apache.catalina.ant.StopTask
.
Discussion
During development, you might need to stop a Tomcat web application so that you can add new servlets or deployment-descriptor entries, and then restart the application, allowing the changes to take effect. In the absence of a conf/server.xml configuration to make the application dynamically reloadable (see Recipe 2.2), you can use an Ant target to stop a particular web application without disrupting the other running web applications. This is the opposite of starting an application (Recipe 4.7); the application is taken out of service until you start it again.
The org.apache.catalina.ant.StopTask
class
provides a connection
between Ant and the
Tomcat Manager
application. Manager is a
built-in web application
(at context path
/manager)
that you can use to
administer other Tomcat
web applications.
Implement the same four steps
discussed in Recipe
4.7
to use this stop
task:
Make sure you have the necessary JAR file required to use the Ant task for stopping Tomcat: <Ant-installation-directory>/lib/catalina-ant.jar. Copy this JAR from the <Tomcat-installation-directory>/server/lib directory to your <Ant-installation-directory>/lib directory (otherwise known as ANT_HOME/lib).
Make sure the Tomcat user database includes a username that is linked to the manager role (see step 2 of Recipe 4.7 if you need more details).
Example 4-9 uses a
taskdef
element to give the task the namestop
, which is used by the target that is responsible for stopping Tomcat.Run the Ant file at the command line by changing to its directory and typing
ant
orant -buildfile
buildfile-name
.
<project name="My Project" default="stop-tomcat" basedir="."><taskdef name="stop" classname="org.apache.catalina.ant.StopTask" />
<!-- import properties specifying username, password, url, and context-path -->
<property file="global.properties" />
<target name="stop-tomcat"
description="Stops the Web application">
<echo message="Stopping the application ${context-path}..."/>
<stop
url="${url}"
username="${username}"
password="${password}"
path="/${context-path}" />
</target>
</project>
The taskdef
defines a task for this
build file called
stop
.
The defined task is then
used in the build file:
<stop url="${url}" username="${username}" password="${password}" path="/${context-path}" />
Example
4-9
gets
its property values from
a property
task that imports
global.properties
(the property file is
located in the same
directory as the Ant
build file). The
properties represent:
The username and password of a user who is mapped to the manager role in conf/tomcat-users.xml
The URL to the Manager application, as in http://localhost:8080/manager
The context path for the web application that you are stopping
Tip
The Tomcat manager application can initiate many other common administrative tasks such as deploying applications (see Recipe 2.6).
See Also
The Tomcat Manager application
description: http://jakarta.apache.org/tomcat/tomcat-4.1-doc/manager-howto.html;
Recipe
4.1
on downloading and
setting up Ant; Recipe
4.2
on writing Ant targets;
Recipe
4.3
on creating a classpath
for an Ant file; Recipe
4.4
on compiling a servlet
with Ant; Recipe
4.5
and Recipe
4.6
on creating WAR and JAR
files; Recipe
4.7
on starting Tomcat with
Ant; Recipe
2.1
and Recipe
2.6
on deploying web
applications using Ant;
the Ant manual section on
the property
task: http://ant.apache.org/manual/CoreTasks/property.html;
the Ant manual segment on
targets
:
http://ant.apache.org/manual/using.html#targets;
the Apache Ant manual
index page: http://ant.apache.org/manual/index.html;
the Apache Ant Project:
http://ant.apache.org.
Get Java Servlet & JSP Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.