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

Problem

You want to download and set up Apache Ant on your computer.

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:

  1. 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.

  2. 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
  3. 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 type ant 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.

  4. Optionally, set the JAVA_HOME environment variable to the directory where your JDK is installed. You might as well set the JAVA_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 the javac or rmic tasks. Tasks are XML elements that do certain jobs in Ant files, such as war (to create Web Archive files) and javac (to compile Java classes with Ant).

  5. 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

Problem

You want to create target elements for developing web applications with an Ant build file.

Solution

Create one or more target elements as child elements of a project element. Make sure the targets 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.

Example 4-1. An Ant build file that echoes a console message
<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.

Example 4-2. Using the depends target attribute to launch a sequence of targets
<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:

  1. The init target first creates a name property that contains the value “Bruce Perry”. The target uses the property task to accomplish this. Recall that tasks do the real work in Ant; targets are simply grouping elements that call one or more tasks.

  2. The show-props target then echoes the values of the name property (created by the init target) and three built-in properties: os.name, os.version, and java.home.

  3. The echo-message target issues its message to the console and returns the value of the basedir property. All of the targets use the echo 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

Problem

You want to establish an Ant classpath that includes various Tomcat JAR files.

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.

Example 4-3. Defining a classpath including Tomcat JAR files
<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. filesets are elements that represent groups of files. The two nested filesets 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.

Example 4-4. Nesting three filesets in a path structure
<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 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.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).

Example 4-5. Compiling a servlet with an Ant build file
<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

Problem

You want to use Ant to create a Web ARchive (WAR) file.

Solution

Use the Ant war task.

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.

Example 4-6. An Ant file using the war task
<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

Problem

You want to create 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).

Example 4-7. Creating a JAR file with Ant
<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.

Tip

The ** pattern is often used in Ant elements; it means “zero or more directories.”

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

Problem

You want to start a web application on Tomcat using an Ant file.

Solution

Use the Tomcat-supplied StartTask task so that Ant can manage Tomcat.

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.

Take these steps to start Tomcat from Ant:

  1. 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).

  2. 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"/>
  3. 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 name start, which is used by the target that is responsible for starting Tomcat.

  4. 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.

Example 4-8. Starting Tomcat using an Ant file
<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

Problem

You want to use Ant to stop a specific Tomcat web application.

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:

  1. 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).

  2. 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).

  3. Example 4-9 uses a taskdef element to give the task the name stop, which is used by the target that is responsible for stopping Tomcat.

  4. Run the Ant file at the command line by changing to its directory and typing ant or ant -buildfile buildfile-name.

Example 4-9. Using Ant to stop a web application
<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.