The Jakarta Project
      The Tomcat Servlet/JSP Container

Buildmanagement for J2EE applications using ANT HOW-TO

Introduction

written by Johannes Fiala, johannes.fiala@fwd.at in May 2003

This HOW-TO covers my experiences how to setup an effective build management structure using ANT.

I'll cover the following aspects how to use ant to build your Tomcat (or other J2EE container) webapp:

  • Build & Run - the basic setup of buildmanagement
  • Why & how you should use one build.xml file for all your webapps
  • How to compile your libraries using ant
  • Checkout libraries from a central lib-repository
  • Building applications for different locations easily (e.g. development site, test site, production site)

After reading this HOWTO, you should be able to effectively build and deploy your web applications in a complex environment.

Note: This guide should apply to all J2EE containers (except the section about deploying using the manager app of Tomcat).

Recommended readings before you continue
Update history

Update 2003-05-10:

Finished Jspc and Deployment sections.

Update 2003-05-04, 22:00 CEDT:

Entered first ideas.

Tested configurations

I tested the following configurations:

  • Tomcat 4.1.24 with JDK 1.4 on Win 2K Professional/Win NT 4.0
  • Tomcat 5.0.1 with JDK 1.4 on Win 2K Professional
Prerequisites

To use this document, you should download and install (=unzip) the following components:

  • Tomcat 4.1.24 or Tomcat 5.0.1
  • Ant 1.5.2 or higher
Basic setup of ANT

After you've installed Tomcat and Ant, you are ready to set up your build environment. Let's suppose you've installed

  • Tomcat to "c:/tomcat-4.1.24"
  • Ant to "c:/ant-1.5.2"

We'll be using the following identifiers for the paths referred in this document:

  • %DEV_HOME% = Your personal development directory (e.g. c:/develop/)
  • %MYAPP_HOME% = Your first project (e.g. c:/develop/devapp/myapp)
  • %CATALINA_HOME% = Your Tomcat installation directory (e.g. c:/tomcat-4.1.24)
  • %ANT_HOME% = Your Tomcat installation directory (e.g. c:/ant-1.5.2)

First, copy %CATALINA_HOME%/server/lib/catalina-ant.jar to %ANT_HOME%/lib/catalina-ant.jar. Next, you have to setup your development-directory. We'll refer to this directory in this document using "MYAPP_HOME" For example you can create the directory %DEV_HOME%/devapp/myapp.

Next, create the following directories beneath c:/develop/devapp/myapp:

  • src
    will contain the sourcecode of your servlets.
  • jsp
    will contain the jsps you write.
  • web
    will contain all your static resources (images, stylesheets, javascript-files, configuration files, WEB-INF/**)
  • build
    will be used by ant to store all files needed to complete the build
  • docs
    will contain the javadocs generated from your sourcefiles.
  • dist
    will contain the finished WAR file to be deployed to your J2EE container

Setting up build.properties and build.xml

After creating the directories, you have to setup build.xml and build.properties to tell ant what and how you want to build.

Setting up build.properties

Store build.properties at %MYAPP_HOME%/build.properties.

app.name=myapp
catalina.home=c:/jakarta-tomcat-4.1.24
java.home=c:/jsdk14
manager.url=http://localhost:8080/manager
manager.username=myuser
manager.password=test

download the build.properties file

Please note that you have to adjust the build.properties file to your own installation directories. Please also make sure the manager.username is listed at %CATALINA_HOME%/conf/tomcat-users.xml with the manager role assigned.

Setting up %CATALINA_HOME%/conf/tomcat-users.xml
...
<role rolename="manager"/>
<user username="myuser" password="test" roles="manager"/>
...
Setting up build.xml

Store build.xml at %MYAPP_HOME%/build.xml.
This means you create a separate build.xml for each project you want to develop with.

download the build.xml file

First steps running ant

After you've created both build.properties and build.xml at your %MYAPP_HOME%-directory, you're ready to start ant:

Go to %MYAPP_HOME% and enter the following to run the first ant build:
ant
ant will do run the following tasks for you: prepare, jspc, merge-descriptors and compile.

Here comes an explanation of the tasks run automatically:

  • prepare: prepares the build by cleaning up temporary directories and removing generated files from the last build.
  • jspc: runs the JspC compiler to create Java Servlets out of your JSPs.
  • merge-descriptors: will create %MYAPP_HOME%/web/WEB-INF/web.xml containing correct references to your JSPs. It takes the original web.xml file from %MYAPP_HOME%/jsp/web-template.xml.
  • compile: will run a full compile of your Java Servlets at %MYAPP_HOME%/src.

JspC issues

"JspC" refers to the Jasper2 compiler, which convers your JSP files into Java servlets. I used the directory src to store the generated JSPs as well as my Java servlet source files.

The next task, "compile" will then compile your servlet files as well as the generated Jsp-Servlets to class files. This means Tomcat will never be required to perform a compilation of one of your JSPs at the server side, which leaves you off with two big advantages:

  • There's no increase in response time when accessing a JSP for the first time, as the Jsp has already been compiled.
  • If there is a low-level error in your JSP, you will notice when JspC is run, not at the server.

Issues you might run into

JspC duplicate naming bug in TC 4.1.18 and before
If you're using a version prior to TC 4.1.24, there have been issues if you used subdirectories and had a jsp with the same filename in multiple directories. These issues (which have been caused by naming conflicts) have been resolved with TC 4.1.24.

JavaEncoding parameter hardcoded to UTF-8
If you want to generate your Jsps with a different encoding than UTF-8, you might be interested in downloading the patch which allows you to use any encoding you want to set: Patch for javaEncoding using JspC

CLASSPATH issues

The following directories will be included in your CLASSPATH for compilation of your source-files:

  • all JAR files stored at %DEV_HOME%/devapp/lib in your CLASSPATH.
  • the most important Tomcat JAR files

Building a distribution (WAR file)

You can create a WAR file using ant dist. This will create a WAR file containing all contents of the %MYAPP_HOME%/build directory conveniently packed into an WAR archive. You can then deploy this WAR file at your favorite J2EE server.

Deploying to Tomcat server using ANT and the manager app

In the build.xml file available for download above, you find task definitions for the following tasks:

  <!-- Configure the custom Ant tasks for the Manager application -->
  <taskdef name="deploy"    classname="org.apache.catalina.ant.DeployTask"/>
  <taskdef name="install"   classname="org.apache.catalina.ant.InstallTask"/>
  <taskdef name="list"      classname="org.apache.catalina.ant.ListTask"/>
  <taskdef name="reload"    classname="org.apache.catalina.ant.ReloadTask"/>
  <taskdef name="remove"    classname="org.apache.catalina.ant.RemoveTask"/>
  <taskdef name="resources" classname="org.apache.catalina.ant.ResourcesTask"/>
  <taskdef name="roles"     classname="org.apache.catalina.ant.RolesTask"/>
  <taskdef name="start"     classname="org.apache.catalina.ant.StartTask"/>
  <taskdef name="stop"      classname="org.apache.catalina.ant.StopTask"/>
  <taskdef name="undeploy"  classname="org.apache.catalina.ant.UndeployTask"/>

The most important tasks for daily usage are deploy, undeploy and list.

  • deploy: uploads the WAR file generated using dist to your Tomcat server
  • undeploy: removes the application from the Tomcat server
  • list: shows the applications currently running at your Tomcat server including the docBase used

I do not recommend using install/remove, as they only work if you have the Tomcat server running locally at your machine (i.e. the docBase will be a local file url). Use deploy/undeploy, as it works with local and remote Tomcats similarly.

ant deploy

ant deploy will perform an HTTP PUT request to the Tomcat server to upload the WAR file. After successful upload (which btw goes to /webapps/manager/myapp.war, myapp.xml), it will add the Context to server.xml file (TC 4.1.24) or to /webapps/myapp.xml (TC 5.0.1) and start the Context and perform any action necessary to initialize it.

ant undeploy

ant undeploy will take the Context off the server, which means it removes the Context-entry from server.xml. It doesn't necessarily mean it will be removed from the manager work directory, as this isn't the case in TC 4.1.24/5.0.1, but that could change as the deployer undergoes further development.

Using a central JAR-file (libraries) repository

The following section explains how to allow for one central repository containing all your libraries used for all your projects. This has the BIG advantage of ensuring consistency across all your apps. If you need different versions of specific JAR-files, you can still do so by naming them differently (including the version identifier).

download the build.xml file with library repository support

To start using the library repository in your myapp-project, you have to do the following:

  1. download the build.xml file from above.
  2. create a file lib.xml containing references to the JAR files of the repository you actually need in your project.
  3. run ant to have the library files you mentioned in lib.xml copied automatically into /build/WEB-INF/lib.

The lib.xml file is really simple and has to use the following syntax:

<include name="mylib.jar" />
<include name="mylib-custom.jar" />
...

You only have ONE version of your build.xml file (copied to every project path, e.g. %MYAPP_HOME%). You specify the different libraries required for each project at the project level (e.g. %MYAPP_HOME%/lib.xml).

Thus, you have ONE central lib repository from which project "checks out" the libraries it needs to be included in its WAR file.

Using different locations

As your project grows, you'll soon have the requirement to have multiple locations you want to deploy your applications to.

A typical location scenario of a mid-size project would be as follows:

  • Development location (e.g. local Tomcat installation on a Windows PC)
  • Testing location (e.g. Tomcat installation on a Linux machine
  • Production location (e.g. Tomcat installation on a Linux machine

download the build.xml file with libraries and multiple location support

Different locations usually use different directory names and different dns-names/urls to be used. This requires you to use different properties files and maybe different context configurations for each location.

To manage different locations easily and just with simple ant commands, I've set up the following idea:

  • Use separate folders for the static files which are specific to a location (e.g. /web-dev, /web-production).
  • Keep the web folder for static files which apply to all locations (/web).
Additionally, set up separate command files, which will overwrite the build.properties file with the build.properties for the current location and start ant with a location parameter set, which indicates which directory will contain the static files for this location.

These are the only files/directories you have to set up to achieve this:

Setting up build.properties files for each location:
  • build-dev.properties
    contains configuration data for location dev
  • web-production
    contains configuration data for location production

Contents of build-dev.properties will point to the local Tomcat server used for development

app.name=forms-1.3.0.5
catalina.home=c:/jakarta-tomcat-4.1.24
java.home=c:/j2sdk1.4.1_01
manager.url=http://localhost:8080/manager
manager.username=myuser
manager.password=test

Contents of build-production.properties will point to the remote Tomcat server used in production

app.name=forms-1.3.0.5
catalina.home=c:/jakarta-tomcat-4.1.24
java.home=c:/j2sdk1.4.1_01
manager.url=http://www.myappserver.com:8080/manager
manager.username=myuser
manager.password=test
Setting up directories for each location

Directories for each location

  • web-dev
    will contain static resources specific to the location "dev"
  • web-production
    will contain static resources specific to the location "dev"
Setting up a cmd file/shell script to build for the required location

For the location dev, I set up a file dev.cmd (dev.sh with Unix) with the following commands:

copy build-dev.properties build.properties
ant -Dlocation=dev %1

This will copy the build-dev.properties to build.properties, to be used by the subsequent ant call. Next, it will start ANT with the proper location set and pass parameters from the commandline to ant.

Now you can build and deploy for the location dev using

  • dev dist
  • dev undeploy
  • dev deploy

Next you have to do the same for the location production (or any other locations you might want to create) and you're ready to live within an multi-location building environment, which is capable to support as many locations as you ever need.

Further applications of the location idea
You can also use the location idea to allow for build for different Tomcat versions. I created a location dev5 to compile and deploy to TC 5.0.1 to perform routine tests against the next version of Tomcat. Of course you can also do this to perform regression tests within the TC 4.x branch.
Open issues

InitParameters don't get inited after deploy
Sometimes when I do ant undeploy and then ant deploy, the new Context doesn't get inited properly, i.e. the InitParameters are set to null instead of their "real" values in context.xml. Often repeating the undeploy/deploy with a small time lag after undeploy helps. As last resort you have to stop and start Tomcat...

Broken JAR files (ClassNotFoundException/ClassFormatException)
Rarely, I get a ClassNotFoundException or ClassFormatException (truncated jar file) after doing undeploy/deploy. Luckily this only occurs rarely. Stopping and starting tomcat helps.

Credits
  • Yoav Shapira: thx for your extensive support at the userlist.
  • Craig McClanahan: thx for writing the manager app.
  • XML/XSLT layout: The XSLT layout has been copied and adapted from the original Tomcat project.

Copyright © Fiala Web Development GmbH, All rights reserved.
written by Johannes Fiala.