How do I build a versioned war file?
Author: Deron Eriksson
Description: This Ant tutorial shows how to build a versioned war file using a customized task
Tutorial created using: Windows XP || JDK 1.5.0_09 || Eclipse Web Tools Platform 1.5.1


Page:    1 2 3 >

This tutorial will build upon much of the work that we've done in other tutorials. In other tutorials, we've created AntSW targets to perform tasks such as using Ant to compile our Java classes, building a war file, securely transferring a war file to a server using pscp, undeploying the web application from TomcatSW, deploying the warW file sitting on the server to Tomcat, and emailing us a message when the web application is done deploying. We also created tasks that allowed us to do such things as create versioned jar files. In addition, we created a customized Ant task that serves as a variable in Ant which is useful since an Ant property can't be changed after it is initially set.

This tutorial will build upon this earlier work to create an Ant target that allows us to automatically build and deploy a versioned war file.

The 'var' task based on the Variable class (that we created in another tutorial ) is included here in the teamcakes-ant-util-1.0.jar file, shown below. In another tutorial, I showed how to include this jarW file in the Ant classpathW so that we can use it, so I won't go over that here.

teamcakes-ant-util-1.0.jar


The ant-utilities build-main.properties file used in this tutorial (minus the juicy info that pertains to me) is included below. For more information about the ant-utilities project, which is created and described elsewhere, see the other Ant tutorials.

ant-utilities build-main.properties


The original ant-utilities build-main.xml file that we'll start with is included below:

original ant-utilities build-main.xml


So, let's start hacking... To begin with, we need to replace two of our old properties with our new variable tasks, since their values are going to change. Personally, I really don't understand why the creators of Ant haven't added a 'variable' element to Ant. I can understand trying to avoid the use of Ant as a programming language by limiting the creation of variables, but personally I'd rather have variables since this can increase code maintainability through reduced code replication. Anyway, in our build-main.xml file, let's replace our 'war-file-name' and 'build-directory' properties with our 'var' task versions of the properties. So I'll replace

	<property name="war-file-name" value="${project-name}.war" />
	<property name="build-directory" value="build" />

with

	<var name="war-file-name" value="${project-name}.war" />
	<var name="build-directory" value="build" />

The only other change that we need to make is to add a 'war-version' target based on our original 'war' target. The original 'war' target is shown here:

	<target name="war">
		<mkdir dir="${build-directory}" />
		<delete file="${build-directory}/${war-file-name}" />
		<war warfile="${build-directory}/${war-file-name}" webxml="${web-xml-file}">
			<classes dir="${classes-directory}" />
			<fileset dir="${web-directory}">
				<!-- Need to exclude it since webxml is an attribute of the war tag above -->
				<exclude name="WEB-INF/web.xml" />
			</fileset>
			<manifest>
				<attribute name="Built-By" value="${builder}" />
				<attribute name="Built-On" value="${build-info.current-date}" />
				<attribute name="Built-At" value="${build-info.current-time}" />
			</manifest>
		</war>
	</target>

The new 'war-version' target is shown below. It is very similar to 'war'. However, first, we change the value of the 'build-directory' variable to be 'build-version' rather than the default 'build'. Then, we make this directory if it doesn't already exist. Next, it creates a build number if it doesn't exist and increments it if it already exists. Next, we create a 'version-number' property that consists of the 'major-version-number' property followed by a period followed by the build number that we either created or incremented. Next, we append the 'version-number' to the 'war-file-name' variable. I added an 'Implementation-Version' attribute set to the version number in the generated MANIFEST.MF file in case we ever needed to look inside the war file and see the version of the war file.

	<target name="war-version">
		<var name="build-directory" value="build-version" />
		<mkdir dir="${build-directory}" />
		<buildnumber />
		<property name="version-number" value="${major-version-number}.${build.number}" />
		<var name="war-file-name" value="${project-name}-${version-number}.war" />
		<war warfile="${build-directory}/${war-file-name}" webxml="${web-xml-file}">
			<classes dir="${classes-directory}" />
			<fileset dir="${web-directory}">
				<!-- Need to exclude it since webxml is an attribute of the war tag above -->
				<exclude name="WEB-INF/web.xml" />
			</fileset>
			<manifest>
				<attribute name="Built-By" value="${builder}" />
				<attribute name="Built-On" value="${build-info.current-date}" />
				<attribute name="Built-At" value="${build-info.current-time}" />
				<attribute name="Implementation-Version" value="${version-number}" />
			</manifest>
		</war>
	</target>

The values of the 'build-directory' and 'war-file-name' variable tasks will be used in any targets and tasks that are executed after they have been set in 'war-version' target. This allows us to use the same targets and tasks to transfer our war file to the server and to deploy it to the server.

Since our 'deploy-from-server' target in build-main.xml uses the 'deploy' Tomcat task, we don't need to make any modifications to this target. The 'deploy' task lets us specify the both the 'localwar' war file name and location on the server, and it also lets us specify the 'path' that we should deploy to, which is basically the name of the web application. Since we set the path equal to '/${project-name}', this maps our versioned war file to the project name.

Our 'tomcat-demo' web application project's build.xml file references our ant-utilities build-main.xml and build-main.properties files. It contains our 'major-version-number' property and our 'project-name' property.

build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="tomcat-demo" default="" basedir=".">

	<property name="major-version-number" value="1" />
	<property name="project-name" value="${ant.project.name}" />
	<property file="../ant-utilities/build-main.properties" />
	<import file="../ant-utilities/build-main.xml" />

</project>

(Continued on page 2)

Page:    1 2 3 >