Support for generics in XDoclet 1.2/1.3 anyone?

05 December 2005

Nicolas Leroux

by Nicolas Leroux

We moved to the latest Java 1.5, and if there is something we love about this new version, it is certainly the use of generics. However, XDoclet support for generics is non-existent. The XDoclet team, did release a new version that allows you to generate classes containing generics, but there is no generics support. So I fixed it.

For example, the following method defined in the EJB bean implementation:

public Collection<Number> ejbFindByCommonKey(Number key)
    throws FinderException

should result in a the following generated method in the local Home interface:

public Collection<myEJBean> findByCommonKey(Number key)
    throws FinderException

Currently, Xdoclet completely ignores the generics and the resulted method is:

public Collection findByCommonKey(Number key)
    throws FinderException

Which, of course, is not exactly what we want to see as we switched to Java 1.5. I therefore tried to 'fix' this bad behavior. After downloading the source code of XDoclet and XJavaDoc, compiling the source code and changing the JavaCC parser, I had it memorize the generic annotation and then it was fairly easy to modify the EJB module to have the desired effect.

Update (6 December 2005): Yesterday evening, I decided to improve the support for CMP. The relationships between the EJB CMP beans are now better handled. For example, if you have the following relationship in your EJB:
/**
 * Getter for CMR Relationship
 *
 * @ejb.interface-method
 *   view-type="local"
 * @ejb.relation
 *   name = "myEJB-myOtherEJBs"
 *   role-name = "myEJB"
 *   target-role-name = "myOtherEJB"
 */
public abstract Collection<myOtherEJB> getOtherEJBs();

/**
 * Setter for CMR Relationship
 *
 * @ejb.interface-method
 *   view-type = "local"
 */
public abstract void setOtherEJBs(Collection<myOtherEJB> value);

It will now generate the following in the local interface:

/**
 * Getter for CMR Relationship
 */
public Collection<myOtherEJB> getOtherEJBs( );

/**
 * Setter for CMR Relationship
 */
public void setOtherEJBs(Collection<myOtherEJB> value);

and update the Deployment Descriptor (ejb-jar.xml) in the appropriate relationship element with:

<ejb-relationship-role>
  <ejb-relationship-role-name>myEJB</ejb-relationship-role-name>
  <multiplicity>One</multiplicity>
  <relationship-role-source>
    <ejb-name>MyEJB</ejb-name>
  </relationship-role-source>
  <cmr-field>
    <cmr-field-name>myOtherEJB</cmr-field-name>
    <cmr-field-type>java.util.Collection</cmr-field-type>
  </cmr-field>
</ejb-relationship-role>

Update (8 December 2005): It seems that I forgot a file in the patch file (the MethodTagsHandler class). I have therefore updated it with the diff for the MethodTagsHandler class. Sorry for the trouble.

Update (16 December 2005): I have made (yet another) mistake putting the binary files in the repository. I have updated with the right binary files (xdoclet-1.3-16122005-lunatech.jar and xdoclet-ejb-module-1.3-16122005-lunatech.jar). Sorry again for the mistake.

Update (19 December 2005): I have updated the xjavadoc library to support fully qualified name on generics. For example:

public class MyBean {

    /**
     * @ejb.interface-method view-type="remote"
     */
     Set<CustomType> bar() {
        /* ... */
     }
}

now generates:

java.util.Set<foo.bar.CustomType> bar();

in the local and remote interface.

Update (8 January 2006): The permission section in the ejb-jar.xml was not correct. It did not strip the generics part, resulting in an invalid xml file. It is now solved. New versions are available at the usual place.

Update (29 January 2006): Fixed a bug where Map<String, String[]> resulted in Map<String, null> . It now generates Map<java.land.String, java.lang.String[]>

The source directory is not up to date. I will try to generate diff files as soon as possible. If you required the source files don't hesitate to contact me.

Here are the source code changes, and the compiled version of xjavadoc and the ejb modules if you want to use it right away without recompiling everything.

Source File and diff changes (using diff -Naur xdoclet-cvs xdoclet-lunatech against the cvs head branch of xdoclet and xjavadoc) are located in the following directory:

Binary Files:

If you are using Eclipse and Jboss-ide, simply copy the files above into <your Eclipse directory>/plugins/org.jboss.ide.eclipse.xdoclet.core_<version>/. Remove the previous version of the library (xjavadoc.jar and xdoclet-ejb-module-1.2.jar).

You will need this library as well DOM4J 1.6.1.

Please remember that this version of XDoclet will only work with JDK1.5. The EJB module and the XDoclet core module have been changed, so feel free to change the other modules to suit your needs.