Completing an EAR - Using XDoclet
(Page 4 of 4 )
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 newControllerServletsource 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>
Using XDoclet
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 thewartarget 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 thewebxmlattribute in the war task to point to the newly generated web.xml file.
Typeantin 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.
Looking Ahead…
We’ve covered a lot of ground in these first few chapters. We now have a single EAR file that encapsulates many moving parts of our J2EE application. We have automated the build process where it is appropriate, and set the stage for future growth.
In the next several chapters, we’ll leave the web tier and move on to the persistence tier. We’ve stored our DTOs in anArrayListfor long enough—let’s tackle saving them in a true database.
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |
|
This article is excerpted from chapter three of the book JBoss at Work: A Practical Guide, written by Tom Marrs and Scott Davis (O'Reilly; ISBN: 0596007345). Check it out today at your favorite bookstore. Buy this book now.
|
|