3.6. Using XDoclet
The last thing we'll do in this chapter is one more tiny bit of automation.
One of the most important
parts
of the WAR file is the deployment descriptor
web.xml
. It lists each servlet and
tells
the servlet container how to deploy them. By maintaining this file by hand, you almost
certainly
guarantee that you will forget to update it when you add new
components
to your application. By using XDoclet in your build process, we can generate it automatically by using nothing but your source code and some well-placed comments.
XDoclet is a collection of custom Ant
tasks
that generate code during the build process. Sometimes XDoclet can generate the necessary code or deployment descriptor using just the source code. At other times, you'll need to add custom comments to nudge XDoclet along in the right direction.
We have only one servlet right now
ControllerServlet
. Example 3-9 shows what your
web.xml
must contain to deploy this servlet correctly.
Example 3-9. web.xml
<!-- servlet definition -->
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>com.jbossatwork.ControllerServlet</servlet-class>
</servlet>
<!-- servlet mapping -->
<servlet-mapping>
<servlet-name>Controller</servlet-name>
<url-pattern>/controller/*</url-pattern>
</servlet-mapping>
Look in
ch03c-xdoclet/src
for the new
ControllerServlet
source code in Example 3-10. Notice the XDoclet comments we've added.
Example 3-10. ControllerServlet.java
/**
* @web.servlet
* name="Controller
"
*
* @web.servlet-mapping
* url-pattern="/controller/*
"
*/
public class ControllerServlet extends HttpServlet
See how they
correspond
to the
web.xml
elements? Now let's look at
build.xml
to see the newly added XDoclet Ant tasks. We first need to create a couple of new
variables
, as in Example 3-11.
Example 3-11. Defining XDoclet variables in build.xml
<property name="xdoclet.lib.dir" value="${env.XDOCLET_HOME} /lib"/>
<property name="gen.source.dir" value=" ${build.dir}/gensrc"/>
Xdoclet.lib.dir
points to the XDoclet jars. If we have a defined
$XDOCLET_HOME
environment variable,
build.xml
should be automatically pointed in the right direction. (Recall that we installed XDoclet in Chapter 1.)
The second variable defines a new location for our dynamically generated code. By keeping our compiled code and generated source code in the same location (
build.dir
), we can easily delete and recreate it each time we run the Ant tasks. It also gently reminds us that we shouldn't store generated artifacts in source control.
Next, we need to set up a new classpath that includes the XDoclet libraries. We keep XDoclet stuff separate from our regular build process, as in Example 3-12. This ensures that we don't inadvertently create dependencies in our deployed code.
Example 3-12. XDoclet Library
Path
in build.xml
<path id="xdoclet.lib.path">
<fileset dir="${xdoclet.lib.dir}">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${compile.lib.dir}">
<include name="**/*.jar"/>
</fileset>
</path>
Next we create the
generate-web
target in Example 3-13.
Example 3-13. generate-web target in build.xml
<!-- ====================================== -->
<target name="generate-web" description="Generate web.xml">
<taskdef name="webdoclet"
classname="xdoclet.modules.web.WebDocletTask"
classpathref="xdoclet.lib.path" />
<mkdir dir="${gen.source.dir}" />
<webdoclet destdir="${gen.source.dir}">
<fileset dir="${source.dir}">
<include name="**/*Servlet.java" />
</fileset>
<deploymentdescriptor destdir="${gen.source.dir}"
distributable="false"
servletspec="2.4" />
</webdoclet>
</target>
Let's step through this:
-
To start, we need to define the WebDoclet task. We don't need to use the <taskdef> tag for
core
Ant tasks, but for third-party tasks, this directive shows Ant where to find the implementation code.
-
Next, we create the destination directory for our generated code.
-
Finally, we call the <webdoclet> task. As you might guess, it generates web-
tier
code. In later chapters, we'll see other XDoclet tasks such as <hibernatedoclet> and <ejbdoclet>.
-
The <filesetdir> tags tells the <webdoclet> task to look for the source code.
-
The <deploymentdescriptor> tag tells <webdoclet> to generate
web.xml
.
-
We use the distributable="false" attribute since we are not in a clustered JBoss environment. It
adjusts
web.xml
appropriately.
To make sure that our new target gets called at the appropriate time, we add it as a dependency to the
war
target in Example 3-14.
Example 3-14. war target in build.xml
<!-- ====================================== -->
<target name="war" depends="
generate-web
,compile"
description="Packages the Web files into a WAR file">
<mkdir dir="${distribution.dir}" />
<war destFile="${distribution.dir}/${war.name}"
webxml="${gen.source.dir}/web.xml"
>
<!-- files to be included in / -->
<fileset dir="${web.dir}" exclude="WEB-INF/web.xml" />
<!-- files to be included in /WEB-INF/classes -->
<classes dir="${classes.dir}" />
<!-- files to be included in /WEB-INF/lib -->
<lib dir="${lib.dir}" />
<!-- files to be included in /WEB-INF -->
<webinf dir="${web.inf.dir}" excludes="web.xml" />
</war>
</target>
Notice that we changed the
webxml
attribute in the war task to point to the newly generated
web.xml
file.
Type
ant
in the
webapp
directory to rebuilt the
subproject
. You should see console output that looks like this:
Buildfile: build.xml
clean:
[delete] Deleting directory /Users/sdavis/Desktop/jbossatwork/ch03/
03c-webdoclet/webapp/build
generate-web:
[mkdir] Created dir: /Users/sdavis/Desktop/jbossatwork/ch03/
03c-webdoclet/webapp/build/gensrc
[webdoclet] (XDocletMain.start 47 )
Running <deploymentdescriptor/>
[webdoclet] Generating web.xml.
compile:
[mkdir] Created dir: /Users/sdavis/Desktop/jbossatwork/ch03/
03c-webdoclet/webapp/build/classes
[javac] Compiling 1 source file to /Users/sdavis/Desktop/jbossatwork/ch03/
03c-webdoclet/webapp/build/classes
war:
[mkdir] Created dir: /Users/sdavis/Desktop/jbossatwork/ch03/
03c-webdoclet/webapp/build/distribution
[war] Building war: /Users/sdavis/Desktop/jbossatwork/ch03/
03c-webdoclet/webapp/build/distribution/jaw.war
all:
BUILD SUCCESSFUL
Total time: 6 seconds
Look at the newly generated
web.xml
in
build/gensrc
. In addition to the required servlet elements, the comments show the various other parts of
web.xml
that can be generated as required by our application. Clearly, we have just scratched the surface of what the
<webdoclet>
task
brings
to the table.
Deploy
jaw.ear
one last time to make sure our application still behaves as expected.
|