ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Using XDoclet: Developing EJBs with Just the Bean Class
Pages: 1, 2

Build: Running XDoclet on the Bean

Now we have one Java source file, ReceiverBean.java, which has been tagged for XDoclet. We need to run XDoclet, telling it to generate all of the fluff for us. The preferred way to run the tool is through the Jakarta-Ant build system. Ant is the ubiquitous Java build system that everyone seems to be using now. If you haven't worked with Ant, check out the Jakarta website, or "Open Source Java: Ant".



The XDoclet folk have developed Ant tasks that we simply place into our build file (build.xml) to invoke the doclet engine. There are two main tasks: <ejbdoclet/> and <webdoclet/>. Since we are working with an EJB, let's peruse the ejbdoclet target in our build file:

<target name="ejbdoclet" depends="prepare">

<taskdef name="ejbdoclet"
         classname="xdoclet.ejb.EjbDocletTask" classpath="${java.class.path};${xdoclet.jar.path};
        ${log4j.jar.path};${ant.jar.path}"/>

<ejbdoclet
sourcepath="${java.dir}"
destdir="${generated.java.dir}"
ejbspec="2.0">

<fileset dir="${java.dir}">
    <include name="**/ReceiverBean.java" />
</fileset>

<remoteinterface/>
<homeinterface/>
<deploymentdescriptor destdir="${build.dir}/ejb/META-INF"/>

<jboss     destdir="${build.dir}/ejb/META-INF"
            version="2.4" xmlencoding="UTF-8" />
<weblogic  destdir="${build.dir}/ejb/META-INF"  
            xmlencoding="UTF-8"
            validatexml="true"/>
<webSphere destdir="${build.dir}/ejb/META-INF" />
<orion     destdir="${build.dir}/ejb/META-INF" />

</ejbdoclet>
</target>

There is a lot of information in this file, so we should break it up and discuss the pieces:

Tag: <taskdef>

First things first; we need to tell the Ant build system about the <ejbdoclet/> tag. We define the name of the tag, the class that implements the tag, and pass in the classpath that it can use. In this case, we use properties that have been set up at the top of the build.xml file that point to the various libraries that we need:

<taskdef name="ejbdoclet" classname="xdoclet.ejb.EjbDocletTask"
classpath="${java.class.path};${xdoclet.jar.path};${log4j.jar.path};
${ant.jar.path}"/>

Tag: <ejbdoclet>

The outermost tag tells Ant to run the EJBDoclet task. We pass in the location of our code, where to generate the XML descriptors and Java source, and the version of the EJB spec we are referring to (again, using properties):

<ejbdoclet
 sourcepath="${java.dir}"
 destdir="${generated.java.dir}"
 ejbspec="2.0">

Tag: <fileset>

We tell the <ejbdoclet> tag where to find our beans, using the <fileset> directive. Our example will find all code named ReceiverBean.java located in any subdirectory of the ${java.dir}:

<fileset dir="${java.dir}">
    <include name="**/ReceiverBean.java" />
 </fileset>

Standard Tags: Interfaces and XML Deployment Descriptors

The next set of tags will make sure that the remote interface, home interface, and standard XML deployment descriptor (ejb-jar.xml) will be generated:

<remoteinterface/>
<homeinterface/>
<deploymentdescriptor destdir="${build.dir}/ejb/META-INF"/>

Vendor-Specific Tags: Interfaces and XML Deployment Descriptors

The final set of tags allow for the generation of vendor-specific deployment descriptors. If you are only deploying your EJBs on one server, you would just have one entry. Since I want my Xbean EJB to be able to be deployed on as many vendor application servers as possible, I placed all of the vendors' tags. It's great that I can generate these vendor-specific files without really knowing anything about the particulars of these app servers!

<jboss     destdir="${build.dir}/ejb/META-INF"
           version="2.4" xmlencoding="UTF-8" />
<weblogic  destdir="${build.dir}/ejb/META-INF"  
           xmlencoding="UTF-8" 
           validatexml="true"/>
<webSphere destdir="${build.dir}/ejb/META-INF" />
<orion     destdir="${build.dir}/ejb/META-INF" />

Now, to build everything for the Xbean EJB, I simply run Ant in the same directory as my build file. I have to make sure that the Ant libraries (ant.jar, jaxp.jar, an XML parser), and the xdoclet.jar file, are in my CLASSPATH. For example, assuming a Windows environment:

% set CLASSPATH=%CLASSPATH%;c:/lib/ant.jar;c:/lib/jaxp.jar;c:/lib/xerces.jar;
  c:/lib/xdoclet.jar;c;/lib/log4j.jar;c:/lib/ejb.jar

% ant ejbdoclet
[runs ant on the ejbdoclet task]

% ant
[runs ant on the default task. In this case it will generate the source, xml descriptors, then compile them, and package everything as an ejb-jar file]

Download the example files from this article here.

Note: Please check out the full build.xml that is part of the examples file accompanying this article/

Extensibility of XDoclet

XDoclet is highly extensible. It has been architected in such a way that you can edit the output of descriptors and interfaces, and create your own through the use of its simple templating mechanism. Each output file has a corresponding template file, with an extension of .j. Open up the xdoclet.jar archive to see a bunch of them. You will see that there are sets of XML tags that have simple logic for knowing what to output from the templates. Here is a simple example taken from the existing EJB template, which will output the display name for the given bean taken from the @ejb:bean display-name property:

<display-name>
 <XDtClass:classTagValue tagName="ejb:bean" 
                         paramName="display-name"/>
</display-name>

This classTagValue XML tag gives a simple interface for displaying a property of a tag. There are a slew of tags that allow for loops, checking if a tag or property exists, and much more. If you ever need to tweak the output or create your own templates, you have support. When would you want to create your own template? How about if you wanted to add support for another application server, or a special O/R database? If you do create your own templates, please submit them to the open source project!

Merge Points: Abstracting XML Deployment Code

Our session bean used the @ejb:env-entry tag to configure an environment variable channelBean with the value com.your.ChannelBean. Do we really want to hard-code this kind of thing in the bean class itself? Maybe not. We have a couple of choices here; one solution is to define the value in the Ant build script. Then, if the value needs to be changed at deploy time we could change the property, and rerun Ant. To make this change we first tweak the build.xml file:

<property name="env-channelBean" value="com.my.ChannelBean" />

and then change the bean class itself:

/**
 *  @ejb:env-entry name="channelBean" type="java.lang.String"   
 *                 value="${env-channelBean}"
 */

Another solution is to use merge points. EJB environment entries have a merge point to allow us the ability to add in our own entries (kind of like a C #include). If we created a file named ejb-entries-<ejbName.xml, it would be sucked into the template mechanism, and will be output in the final ejb-jar.xml.

Conclusion

We have shown how to develop EJBs using XDoclet. This free open source solution can simplify your EJB development, allowing you to work just with a bean class and have the interfaces and descriptors generated for you. This framework is growing, and isn't just for EJBs. Being able to flag methods that you wish to become available via SOAP, configuring your Web applications (even for using Struts) is great. Over time, there will be more and more additions. Some other tools even generate XDoclet tags for you, such as the Middlegen code generation tool for EJB 2.0 Entity Beans.

Dion Almaer is a Principal Technologist for The Middleware Company, and Chief Architect of TheServerSide.Com J2EE Community.


Return to ONJava.com.