Section 9.5. Using XDoclet


9.5. Using XDoclet

XDoclet is an open source code generation engine designed for use with Ant, and you can pick it up for free at http://xdoclet.sourceforge.net/. It'll write code for you, especially deployment descriptors, and is often used for Web and EJB development. XDoclet comes with a number of Ant tasks built-in, shown in Table 9-9.

Table 9-9. The XDoclet Ant tasks

Ant task

Does this

doclet

Specifies the base class for all XDoclet Ant tasks

ejbdoclet

Specifies which EJB-specific subtasks to execute

hibernatedoclet

Specifies which Hibernate subtasks to execute

jdodoclet

Specifies which JDO-specific subtasks to execute

jmxdoclet

Specifies which JMX-specific subtasks to execute

mockdoclet

Generates mock doclet objects

portletdoclet

Specifies which portlet-specific subtasks to execute

webdoclet

Specifies which Web-specific subtasks to execute


XDoclet lets you generate code and deployment descriptors by embedding tags in your code, much like the tags you'd use for Javadoc. There are entire books written about XDoclet because it's an extensive tool. Though there's not room for that level of coverage herethis is a book about Ant, not XDocletI'll take a look at several examples creating Web and EJB applications here, giving the XDoclet story from Ant's point of view.

9.5.1. Developing Applications

You use the XDoclet webdoclet task to develop Web applications. The attributes of this task appear in Table 9-10, and the possible nested elements in Table 9-11.

Table 9-10. The webdoclet Ant tasks

Attribute

Description

Required

addedTags

Specifies you want to add JavaDoc tags to the generated classes

No

destDir

Specifies the destination directory for the generated output

If destDir is not specified by a subtask.

excludedTags

Specifies tags that should not be automatically written to output files

No

force

Specifies you want generation of files to be forced

No

mergeDir

Specifies the directory where subtasks will look for files that they should merged with their generated files

No, but should be set if you want to use the merge feature.

verbose

Specifies you want verbose feedback

No


Table 9-11. The webdoclet Ant task's nested elements

Element

Description

configParam

Specifies configuration parameters you want to use

deploymentdescriptor

Specifies you want to generate a web.xml deployment descriptor

fileset

Specifies a fileset to indicate the files to parse

jbosswebxml

Specifies you want to generate a jboss-web.xml deployment descriptor

jonaswebxml

Specifies you want to generate a web application deployment descriptor for JOnAS

jrunwebxml

Specifies you want to generate a jrun-web.xml deployment descriptor

jsptaglib

Specifies you want to generate a taglib.tld deployment descriptor for JSP taglibs

packageSubstitution

Substitutes a new package for the package in generated files

resin-web-xml

Specifies you want to generate web.xml with Resin extensions

strutsconfigxml

Specifies you want to generate a struts-config.xml deployment descriptor

strutsvalidationxml

Specifies you want to generate a Struts Validator validation.xml deployment descriptor

subTask

Specifies a subtask for this task

weblogicwebxml

Specifies you want to generate a weblogic.xml deployment descriptor for Web applications

webspherewebxml

Specifies you want to generate WebSphere specific deployment descriptors

webworkactiondocs

Specifies you want to generate HTML files containing descriptions of WebWork actions

webworkactionsxml

Specifies you want to generate an actions.xml file

webworkconfigproperties

Specifies you want to generate a views.properties file


You use tags prefixed with an @ to tell XDoclet what you want it to do. In Example 9-6, in this servlet's code, ServletApp.java, I'm telling Ant how to set up the deployment descriptor, web.xml.

Example 9-6. The servlet's code ch09/servlet/ServletApp.java
package app.web; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; /**  * @web.servlet  *     display-name="Servlet App"  *     load-on-startup="1"  *     name="ServletApp"  *  * @web.servlet-init-param  *     name="param1"  *     value="value1"  *  * @web.servlet-init-param  *     name="param2"  *     value="value2"  *  * @web.servlet-mapping  *     url-pattern="/app/*"  *  * @author Steve  */ public class ServletApp extends HttpServlet {     public void doPost(HttpServletRequest request, HttpServletResponse response)             throws IOException, ServletException      {         response.getWriter( ).println("No worries.");     } }

To use webdoclet from Ant, you have to use a taskdef task this way to set up the webdoclet task (See Chapter 12):

        <taskdef             name="webdoclet"             classname="xdoclet.modules.web.WebDocletTask"             classpathref="app.class.path"/>

To create web.xml for this servlet, you use a deploymentdescriptor element inside the webdoclet element:

            <deploymentdescriptor                 servletspec="2.3"                 destdir="${app.web-inf.dir}"/>

The complete build file appears in Example 9-7. It compiles the code, creates web.xml, and is designed to be used from a directory named build right under the XDoclet directory (xdoclet-1.2.1 is the current version as of this writing), while the servlet's code is stored in the directory build/src/java/app/web.

Example 9-7. The servlet's build file ch09/servlet/build.xml
<?xml version="1.0"?> <project default="main" basedir=".">     <property name="lib.dir" value="../lib"/>     <property name="app.dir" value="."/>     <property name="app.dist.dir" value="${app.dir}/output"/>     <property name="app.src.dir" value="${app.dir}/src"/>     <property name="app.java.dir" value="${app.src.dir}/java"/>     <property name="app.generated-src.dir" value="${app.dist.dir}/generated-src"/>     <property name="app.web-inf.dir" value="${app.dist.dir}/web-inf"/>     <property name="app.classes.dir" value="${app.dist.dir}/classes"/>     <property name="app.xdoclet.force" value="false"/>     <path >         <fileset dir="${lib.dir}">             <include name="*.jar"/>         </fileset>     </path>     <target name="init">         <tstamp>             <format property="TODAY" pattern="d-MM-yy"/>         </tstamp>         <taskdef             name="webdoclet"             classname="xdoclet.modules.web.WebDocletTask"             classpathref="app.class.path"/>         <mkdir dir="${app.classes.dir}"/>         <mkdir dir="${app.generated-src.dir}"/>     </target>     <target name="webdoclet" depends="init">         <webdoclet             destdir="${app.generated-src.dir}"             excludedtags="@version,@author,@todo"             force="${app.xdoclet.force}"             verbose="false">             <fileset dir="${app.java.dir}">                 <include name="**/Servlet*.java"/>             </fileset>             <deploymentdescriptor                 servletspec="2.3"                 destdir="${app.web-inf.dir}"/>         </webdoclet>     </target>     <target name="compile" depends="webdoclet">         <javac             destdir="${app.classes.dir}"             classpathref="app.class.path"             debug="on"             deprecation="on"             optimize="off">             <src path="${app.java.dir}"/>             <src path="${app.generated-src.dir}"/>         </javac>     </target>     <target name="main" depends="compile">         <echo>Using XDoclet....</echo>     </target> </project>

When you run this build file, it'll create a complete web.xml for this servlet; here is the crucial part:

   <servlet>       <servlet-name>ServletApp</servlet-name>       <display-name>Servlet App</display-name>      <servlet-class>app.web.ServletApp</servlet-class>       <init-param>          <param-name>param1</param-name>          <param-value>value1</param-value>       </init-param>       <init-param>          <param-name>param2</param-name>          <param-value>value2</param-value>       </init-param>       <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>       <servlet-name>ServletApp</servlet-name>       <url-pattern>/app/*</url-pattern>    </servlet-mapping>

In this way, XDoclet can write deployment descriptors for you if you remember to put all needed information in your source code files using XDoclet tags.

9.5.2. Working with EJB Containers

This XDoclet Ant task executes EJB-specific sub-tasks to support EJB development. You can see the attributes of this task in Table 9-12. The legal nested elements appear in Table 9-13.

Table 9-12. The ejbdoclet Ant task's attributes

Attribute

Description

Required

Default

addedTags

Specifies you want to add JavaDoc tags to the generated classes.

No

 

destDir

Specifies the destination directory to use for output files.

If destDir is not specified for a subtask.

 

ejbClassNameSuffix

Specifies suffixes that should be removed from the bean classname. A comma-separated list.

No

"Bean, EJB, Ejb"

ejbSpec

Specifies the version of EJB specification ejbdoclet should use. Possible values: 1.1 and 2.0.

No. Default is 2.0.

 

excludedTags

Specifies tags that should not be written to output files.

No

 

force

Specifies whether you want to force the the generation of files if needed.

No

 

mergeDir

Specifies the directory where subtasks will look for files that they should merge with their generated files.

No, but should be set if you use the merge feature.

 

verbose

Specifies you want verbose feedback.

No

 


Table 9-13. The ejbdoclet Ant task's nested elements

Element

Description

apachesoap

Provides support for Apache SOAP subtasks

axisdeploy

Provides support for axis deployment

axisundeploy

Provides support for axis undeployment

borland

Provides support for Borland code

castormapping

Specifies you want to generate a mapping.xml deployment descriptor

configParam

Specifies configuration parameters that will be included as an attribute/value pair

dao

Provides support for DAO

dataobject

Provides support for data objects for Entity EJBs.

deploymentdescriptor

Creates a deployment descriptor

easerver

Provides support for configuration files for EJB JAR files in EAServer 4.1+

entitybmp

Creates entity bean classes for BMP entity EJBs

entitycmp

Creates CMP layer code

entityfacade

Provides support for entity facades

entitypk

Creates primary key classes for entity EJBs

fileset

Specifies a fileset of files to parse

homeinterface

Provides support for remote home interfaces for EJBs

hpas

Provides support for an hp-ejb-jar.xml deployment descriptor for HPAS

jboss

Provides support for jboss.xml, jaws.xml, and/or jbosscmp-jdbc.xml deployment descriptors for JBoss

jonas

Provides support for the deployment descriptor for JOnAS

jrun

Provides support for jrun.

localhomeinterface

Generates local home interfaces for EJBs

localinterface

Generates local interfaces for EJBs

mvcsoft

Generates MVCSoft's XML

oc4j

Generates OC4J specific deployment descriptor (orion-ejb-jar.xml)

openejb

Provides support for openejb-jar.xml deployment descriptors for OpenEJB

orion

Provides support for Orion's orion-ejb-jar.xml

packageSubstitution

Specifies you want to substitute a new package for the package in generated files

pramati

Provides support for Pramati deployment files

remotefacade

Provides support for stage 2 of remote facade generation

remoteinterface

Provides support for remote interfaces for EJBs

resin-ejb-xml

Provides support for Resin

session

Provides support for sessions

strutsform

Provides support for a Struts ActionForm, based on an entity EJB

subTask

Specifies a subtask for this task

sunone

Provides support for configuration files for EJB jars in iPlanet/SunONE

utilobject

Provides support for util objects

valueobject

Provides support for value objects for Entity EJBs

weblogic

Generates deployment descriptors for WLS 6.0, 6.1, and 7.0

websphere

Generates EJB-related files from one or a set of EJB bean source files that uses custom EJBDoclet JavaDoc tags


The source code for an EJB, Appbean.java, appears in Example 9-8 and shows how the ejbdoclet task works. The embedded XDoclet tags hold data for the ejbdoclet task, which will create a deployment descriptor and write code.

Example 9-8. The EJB bean ch09/ejb/Appbean.java
package app.web; import javax.ejb.*; /**  *  * @ejb.bean name="App"  *    description="App example bean"  *    jndi-name="ejb/App"  *    type="Stateless"  *  * @ejb.security-role-ref role-link="Administrator"  *    role-name="admin"  *  * @ejb.permission   role-name="App"  * @ejb.permission   role-name="Administrator"  *  * @ejb.transaction  type="Required"  * @ejb.transaction-type type="Container"  *  * @author Steven  */ public abstract class AppBean implements SessionBean  {     /**      * Add and return values.      *      * @ejb.interface-method view-type="remote"      */     public double adder(int x, int y)      {         return x + y;     }     public void ejbActivate( )      {     }     public void ejbPassivate( )      {     }     public void setSessionContext(SessionContext ctx)      {     }     /**      * Remove      *      * @ejb.transaction      *    type="Mandatory"      */     public void ejbRemove( )      {     } }

In the build file, you use taskdef to tell Ant about the ejbdoclet task:

        <taskdef             name="ejbdoclet"             classname="xdoclet.modules.ejb.EjbDocletTask"             classpathref="app.class.path"/>

Include the .jar file containing Sun's javax.ejb.* classes on the taskdef task's classpath when creating the ejbdoclet task in a build file.


You can create a deployment descriptor, ejb-jar.xml, with the deploymentdescriptor element:

            <deploymentdescriptor                 destdir="${app.meta-inf.dir}"                 description="ejbbean"/>

The entire build file appears in Example 9-9. This file is designed to be run from a directory named ejbbuild right under the XDoclet unzip directory with the servlet's code in the directory build/src/java/app/web.

Example 9-9. The EJB bean build file ch09/ejb/build.xml
<?xml version="1.0" ?> <project default="main" basedir=".">     <property name="lib.dir" value="../lib"/>     <property name="app.dist.dir" value="output"/>     <property name="app.src.dir" value="src"/>     <property name="app.java.dir" value="${app.src.dir}/java"/>     <property name="app.generated-src.dir" value="${app.dist.dir}/generated-src"/>     <property name="app.web-inf.dir" value="${app.dist.dir}/web-inf"/>     <property name="app.classes.dir" value="${app.dist.dir}/classes"/>     <property name="app.lib.dir" value="lib"/>     <property name="app.meta-inf.dir" value="meta-inf"/>     <property name="app.xdoclet.force" value="false"/>     <path >         <fileset dir="${lib.dir}">             <include name="*.jar"/>         </fileset>         <fileset dir="${app.lib.dir}">             <include name="*.jar"/>         </fileset>     </path>     <target name="init">         <tstamp>             <format property="TODAY" pattern="d-MM-yy"/>         </tstamp>         <taskdef             name="ejbdoclet"             classname="xdoclet.modules.ejb.EjbDocletTask"             classpathref="app.class.path"/>         <mkdir dir="${app.classes.dir}"/>         <mkdir dir="${app.generated-src.dir}"/>         <mkdir dir="${app.meta-inf.dir}" />     </target>     <target name="ejbdoclet" depends="init">         <ejbdoclet             destdir="${app.generated-src.dir}"             mergedir="parent-fake-to-debug"             excludedtags="@version,@author,@todo"             ejbspec="2.0"             force="${app.xdoclet.force}"             verbose="false">             <fileset dir="src/java">                 <include name="**/*.java"/>             </fileset>             <remoteinterface/>             <localinterface/>             <homeinterface/>             <localhomeinterface/>             <entitycmp/>             <entitybmp/>             <session/>             <deploymentdescriptor                 destdir="${app.meta-inf.dir}"                 description="ejbbean"/>         </ejbdoclet>     </target>     <target name="compile" depends="ejbdoclet">         <javac             destdir="${app.classes.dir}"             classpathref="app.class.path"             debug="on"             deprecation="on"             optimize="off">             <src path="${app.java.dir}"/>             <src path="${app.generated-src.dir}"/>         </javac>     </target>     <target name="main" depends="compile">         <echo>Using EJBDoclet....</echo>     </target> </project>

Running this build file creates EJB interface code and a deployment descriptor, ejb-jar.xml. Here is the relevant part of the generated ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"  "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar >    <description><![CDATA[ejbbean]]></description>    <display-name>Generated by XDoclet</display-name>    <enterprise-beans>       <!-- Session Beans -->       <session >          <description><![CDATA[App example bean]]></description>          <ejb-name>App</ejb-name>          <home>app.web.AppHome</home>          <remote>app.web.App</remote>          <local-home>app.web.AppLocalHome</local-home>          <local>app.web.AppLocal</local>          <ejb-class>app.web.AppSession</ejb-class>          <session-type>Stateless</session-type>          <transaction-type>Container</transaction-type>          <security-role-ref>             <role-name>admin</role-name>             <role-link>Administrator</role-link>          </security-role-ref>       </session>         .         .         .    <!-- Assembly Descriptor -->    <assembly-descriptor >      <!--        To add additional assembly descriptor info here, add a file to your        XDoclet merge directory called assembly-descriptor.xml that contains        the <assembly-descriptor></assembly-descriptor> markup.      -->       <security-role>          <role-name>App</role-name>       </security-role>       <security-role>          <role-name>Administrator</role-name>       </security-role>       <method-permission >          <role-name>App</role-name>          <role-name>Administrator</role-name>          <method >             <ejb-name>App</ejb-name>             <method-name>*</method-name>          </method>       </method-permission>         .         .         .    <!-- transactions -->    <container-transaction >       <method >          <ejb-name>App</ejb-name>           <method-name>*</method-name>        </method>        <trans-attribute>Required</trans-attribute>     </container-transaction>    <container-transaction >       <method >          <ejb-name>App</ejb-name>          <method-intf>LocalHome</method-intf>          <method-name>remove</method-name>          <method-params>          </method-params>       </method>       <trans-attribute>Mandatory</trans-attribute>    </container-transaction>    <container-transaction >       <method >          <ejb-name>App</ejb-name>          <method-intf>Home</method-intf>          <method-name>remove</method-name>          <method-params>          </method-params>       </method>       <trans-attribute>Mandatory</trans-attribute>    </container-transaction>         .         .         . </ejb-jar>

XDoclet is a powerful tool that's still developing. Currently, you can only run it in Ant, but a command-line tool is in the works. Once you get the hang of it, XDoclet helps with Web and EJB application development in a way that makes sense; when you modify your code, you modify the deployment descriptors and the EJB code you generate at the same time. It's a tool worth watching.



    Ant. The Definitive Guide
    Ant: The Definitive Guide, 2nd Edition
    ISBN: 0596006098
    EAN: 2147483647
    Year: 2003
    Pages: 115
    Authors: Steve Holzner

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net