9.5 Generating the EJB Deployment Descriptor

9.5.1 Problem

You want to use XDoclet to generate the EJB deployment descriptor, ejb-jar.xml.

9.5.2 Solution

Add the necessary XDoclet tags to your EJB source files and update your Ant buildfile to use XDoclet to generate the deployment descriptor.

9.5.3 Discussion

Anyone who has worked with EJBs knows that maintaining deployment descriptors is tedious and often frustrating, especially when dealing with a large number of beans. If a syntax error creeps into the deployment descriptor, you may not know until you have deployed the application to the server. Even then the error messages you receive may or may not be helpful to pinpoint the problem. Another problem is that the deployment descriptors and source files can get out of sync, causing even more deployment frustrations. The solution is to use XDoclet to generate the deployment descriptors whenever an EJB change is made.

Avoiding duplication is a key to simple, maintainable code. XDoclet allows you to make changes in one place and generate all of the tedious, duplicated code.

It is also worth mentioning that XDoclet is immensely less labor-intensive than using point-and-click GUI tools provided by most commercial IDEs. Once the development environment is configured, the Ant build process magically does the dirty work.

XDoclet provides a simple mechanism for generating EJB deployment descriptors. The first step is to mark up the EJB with the necessary XDoclet tags. Example 9-2 shows how this might be done for a stateless session bean.

Example 9-2. Marking up a stateless session bean
package com.oreilly.javaxp.xdoclet.ejbdoclet.ejb;

import javax.ejb.SessionBean;

/**
 * @ejb.bean
 *     type="Stateless"
 *     name="PaymentProcessingBean"
 *     jndi-name="ejb/PaymentProcessingBean"
 *     view-type="remote"
 * @ejb.transaction
 *     type="Required"
 * @ejb.transaction-type
 *     type="Container"
 *
 * @author Brian M. Coyner 
 */
public abstract class PaymentProcessingBean implements SessionBean {

    /**
     * @ejb.interface-method view-type="remote"
     */
    public boolean makePayment(String accountNumber, double payment) {
        // perform logic to look up customer and make payment against their
        // account
        return true;
    }
}

The @ejb.bean tag defines information about the bean. This information is used when generating the enterprise-beans section of the deployment descriptor. We define the bean to be a stateless session bean named PaymentProcessingBean, with a JNDI name of ejb/PaymentProcessingBean. There are numerous other attributes that you may include with this tag that are not shown in this example. See the XDoclet documentation for all possible tags and their usage.

The @ejb.transaction-type tag defines how the container should manage the transactions for the bean. Valid values are "Container" and "Bean". The default is "Container".

The @ejb.transaction tag defines a single transactional attribute for all methods defined in the bean. Valid values are "NotSupported", "Supports", "Required", "RequiresNew", "Mandatory", or "Never". The attribute may be omitted if different methods in the bean need different transactional attributes. The @author tag was left to show that you can mix and match XDoclet tags with other tags.

The next step is to tell the ejbdoclet task to generate the deployment descriptor. Here is an example:

<ejbdoclet
    ejbspec="2.0"
    destdir="${dir.generated.src}"
    excludedtags="@author"
    force="${force.ejb}">

  <!-- other subtasks left out for brevity --> 

  <deploymentdescriptor destdir="${dir.ejb.metainf}" validateXML="true"/>
</ejbdoclet>

The deploymentdescriptor subtask tells XDoclet to generate the deployment descriptor file (ejb-jar.xml) and write it to a directory defined by the property dir.ejb.metainf. Setting the optional attribute validateXML to "true" validates the generated XML file against its DTD or XML Schema.

Now let's look at the generated ejb-jar.xml file.[3]

[3] This example has been cleaned up for this recipe because the actual generated file is not nicely formatted.

<?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>No Description.</description>
  <display-name>Generated by XDoclet</display-name>
  <enterprise-beans>
    <session>
      <description><![CDATA[No Description.]]></description>
      <ejb-name>PaymentProcessingBean</ejb-name>    
      <home>
        com.oreilly.javaxp.xdoclet.ejbdoclet.interfaces.PaymentProcessingBeanHome
      </home>
      <remote>
        com.oreilly.javaxp.xdoclet.ejbdoclet.interfaces.PaymentProcessingBean
      </remote>
      <ejb-class>
        com.oreilly.javaxp.xdoclet.ejbdoclet.ejb.PaymentProcessingBeanSession
      </ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
    </session>
  </enterprise-beans>

  <assembly-descriptor>
    <container-transaction>
      <method>
        <ejb-name>PaymentProcessingBean</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
    </container-transaction>
  </assembly-descriptor>
</ejb-jar>

XDoclet frees you from having to manage the deployment descriptor yourself. You simply mark up your EJB class with the necessary tags, execute the ejbdoclet task, and deploy your application. The majority of the time you never have to bother looking at the deployment descriptor.

9.5.4 See Also

Recipe 9.7 shows how to generate the home and remote interfaces, removing yet another tedious task from EJB development.