Apache offers a tool called TCD (Tomcat Client Deployer) which can be used to deploy web application REMOTELY.
The tool relies on Tomcat Manager application.
TCD can be easily integrated into ANT build script. Along with TCD distribution there is a template build.xml. I extract some common information and add some information useful to myself.
Properties used by this build file are from two external sources. One is the global properties file, which contains properties that suitable to all my web applications. Properties defined in this file should be identical to all applications. The other one is a project-specific properties file. This one should be placed into the root folder of the project.
The global properties file is,
tomcat.manager.url=http://192.168.140.100:8080/manager
tomcat.manager.username=admin
tomcat.manager.password=admin
tomcat.deployer.jars.dir=C:/Java/apache-tomcat-5.5.20-deployer/lib
The project-specific properties file,
# The location containing your source files
src=src
# The location containing the exploded web application
webcontent=WebContent
# The context path of the web application
contextpath=/myWebapp
The complete ANT build file is:
<project name="myWebApp" default="compile" basedir=".">
<!-- This value is intended to be override from command-line -->
<property name="configs.dir" value="c:/java/configs"/>
<!-- import properties from global properties definition file -->
<!--
properties to access the Manager application
properties to the location of the dployer jars
-->
<property file="${configs.dir}/build.properties"/>
<!-- import project-scope properties -->
<property file="build.properties"/>
<!-- Configure the directory into which the web application is built -->
<property name="build" value="${basedir}/build"/>
<!-- Configure the folder and context path for this application -->
<property name="src.dir" location="${src}"/>
<property name="webapp" value="${webcontent}"/>
<property name="path" value="${contextpath}"/>
<property name="webapp.path" value="${build}/webapp${path}"/>
<path id="deployer.classpath">
<fileset dir="${tomcat.deployer.jars.dir}">
<include name="*.jar"/>
</fileset>
</path>
<!-- Configure the custom Ant tasks for the Manager application -->
<taskdef resource="org/apache/catalina/ant/catalina.tasks"
classpathref="deployer.classpath"/>
<!-- Executable Targets -->
<target name="clean" description="Removes build directory">
<delete dir="${build}" />
</target>
<target name="compile" description="Compile web application"
depends="clean">
<!-- clone the exploded web application folder -->
<copy todir="${webapp.path}">
<fileset dir="${webapp}"/>
</copy>
<!-- compile all jsps. all generated class files will be put into WEB-INF/classes folder -->
<jasper2 validateXml="false"
uriroot="${webapp.path}"
webXmlFragment="${webapp.path}/WEB-INF/generated_web.xml"
addWebXmlMappings="true"
outputDir="${webapp.path}/WEB-INF/classes" />
<validator path="${webapp.path}" />
<mkdir dir="${webapp.path}/WEB-INF/classes"/>
<mkdir dir="${webapp.path}/WEB-INF/lib"/>
<javac destdir="${webapp.path}/WEB-INF/classes"
optimize="off"
debug="${compile.debug}"
deprecation="${compile.deprecation}"
failonerror="false"
srcdir="${src.dir}"
encoding="UTF-8"
excludes="**/*.smap">
<classpath>
<fileset dir="${webapp.path}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<fileset dir="${basedir}/lib">
<include name="*.jar"/>
</fileset>
</classpath>
<include name="**" />
<exclude name="tags/**" />
</javac>
<!-- create the war archive -->
<jar destfile="${webapp.path}.war"
basedir="${webapp.path}" />
</target>
<target name="deploy" description="Deploy web application">
<deploy url="${tomcat.manager.url}" username="${tomcat.manager.username}" password="${tomcat.manager.password}"
path="${path}" war="${webapp.path}.war" update="true" />
</target>
<target name="undeploy" description="Undeploy web application">
<undeploy url="${tomcat.manager.url}" username="${tomcat.manager.username}" password="${tomcat.manager.password}"
path="${path}"/>
</target>
<!-- Webapp lifecycle control -->
<target name="start" description="Start web application">
<start url="${tomcat.manager.url}" username="${tomcat.manager.username}" password="${tomcat.manager.password}"
path="${path}"/>
</target>
<target name="reload" description="Reload web application">
<reload url="${tomcat.manager.url}" username="${tomcat.manager.username}" password="${tomcat.manager.password}"
path="${path}"/>
</target>
<target name="stop" description="Stop web application">
<stop url="${tomcat.manager.url}" username="${username}" password="${tomcat.manager.password}"
path="${path}"/>
</target>
In above build file, <jasper2> task will compile all JSPs
<jasper2 validateXml="false"
uriroot="${webapp.path}"
webXmlFragment="${webapp.path}/WEB-INF/generated_web.xml"
addWebXmlMappings="true"
outputDir="${webapp.path}/WEB-INF/classes" />
webXmlFragment attribute specifies the name of the web.xml fragment generated by jasper2 during the JSP compilation.
addWebXmlMappings = true will cause jasper automatically merge the ${webapp.path}/WEB-INF/generated_web.xml with the current web application deployment descriptor at ${webapp.path}/WEB-INF/web.xml.
Reload won‘t transfer war file to server. It just tells server to reload the specified web application from server local file system. So it is more useful to be used with local Tomcat and an exploded web application.
Question
I wonder why the jasper2 task is called prior to javac. I think javac should be performed first to get the freshest class file, then copy the folder of webcontent and do JSP compilation. The copy won‘t overwrite the freshest class file as we don‘t let it do so via overwrite attribute.