JaVa
   

A Simple Example

By far the crowning jewel in the XDoclet arena involves ejbdoclet and the ability to produce all of the files necessary to support EJBs. For this reason it is fitting to use the ejbdoclet task as the foundation for a simple example before moving to the remaining chapters, where we will provide much more information on using XDoclet with various technologies, including EJBs. In this example, we will build an entity bean for the following table:

CREATE TABLE comments (
 ID int not null auto-increment primary key, storylD int,
 comment varchar(255),
 ts timestamp
);


This simple table can be used to store comments about a story as you might find in a portal-type app. For our environment, we will assume the existence of Java, Ant, and XDoclet on the development system. For our entity bean, we will need to produce four different files:

Using XDoclet, we need only to write a single file, the implementation file, and include the appropriate XDoclet files. Here's an example of the implementation file we produced using XDoclet tags:

package com.company.database;
/**
 * @ejb.bean type="CMP" * cmp-version="2.x"
 * * jndi.name="cmr/User" * view-type="local" * primkey-field="ID"
 *
 * @ejb.pk class="java.lang.Integer"
 *
 * @ejb:finder signature="java.util.Collection findAll()" * unchecked="true"
 * query="SELECT OBJECT(s) FROM comment AS s"
 *
 * @ejb.home generate="local"
 * local -class="database.CommentHome"
 *
 * @ejb.interface generate="local" * local-class="database.Comment"
 *
 * @ejb-persistence table- 
*/
public abstract class CommentBean extends EntityBean { private EntityContext ctx;
 private String ID;
 private String StorylD;
 private String Comment;
 private String ts;
/**
 * @ejb.pk-field
 * @ejb.interface-method view-type="local" * @ejb.persistent-field
*/
public abstract String getID() {
}
/**
* @ejb.interface-method view-type="local" * @ejb.persistent-field
*/
public abstract String getStoryID() {
}
/**
* @ejb.interface-method view-type="local" * @ejb.persistent-field
*/
public abstract String getComment() {
}
/**
* @ejb.interface-method view-type="local" * @ejb.persistent-field
*/
public abstract String getTs() {
}
/**
* @ejb.interface-method view-type="local" */
public abstract void setStoryID(String id) {
}
/**
* @ejb.interface-method view-type="local" */
public abstract void setComment(String comment) {
}
/**
* @ejb.interface-method view-type="local" */
public abstract void setTs(String ts) {
}
public Integer ejbCreate(String c, String s, String t) throws CreateException {
 setStorylD(s);
 setComment(c);
 setTs(t);
}
public void ejbPostCreate(String c, String s, Stringt) { }
public void ejbRemove() throws RemoveException { }
public void ejbStore() {
}
public void ejbLoad() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
public void setEntityContext(EntityContext ctx) {
 this.ctx = ctx;
}
public void unsetEntityContext() { this.ctx = null;
}


As you can clearly see, the implementation file for our entity bean consists primarily of tags and just a few actual Java statements. Before we look at an Ant build script to process our implementation file, let's take a moment and discuss what each of the tags is telling the XDoclet processor to generate. All of the XDoclet tags have a common format:

@namespace.tag-name attribute-name="attribute value"


The @namespace part of the tag relates to the tasks defined for XDoclet. We will touch on tasks later in the chapter, but tasks include ejb, hibernate, and others. A tag can be zero or more attributes, depending on how they are defined. Each attribute will have a value associated with it to help with the code generation. A full description of all tags available in XDoclet can be found at http://xdoclet.sourceforce.net. Looking back at our code, the first comment block is used to control the code generation for the entire bean class. The tag, @ejb.bean, sets the tone for the entire code generation in that it indicates to the generator that we are going to be building an EJB bean. As you can see, our XDoclet tags aren't restricted to just a description as in the case of Javadoc tags, but instead we have some number of attributes for the tag. In our example, the @ejb.bean tag is using six different attributes:

type="CMP" cmp-version="2.x" jndi.name="cmr/User" view-type="local" primkey-field="ID"


The type="CMP" attribute, or parameter, indicates the bean we are building will be container managed. The cmp-version="2.x" attribute indicates the CMP version begin used. The attribute tells the code generator the name of the bean being created. The bean name is the same as the class name defined within the implementation file, as our example shows. The jndi.name="cmr.user" attribute indicates the value to use for the jndi component. The view-type="local" attribute indicates the access type of this bean. The options here include local, remote, and both. The primkey-field="ID" attribute indicates which column within our table relating to the bean is used as the primary key field. Looking back at our schema for the database table, we can see that the ID field has the clause of primary key associated with it, so that field is used as the value for this attribute. Now that the code generator knows we are building an EJB, we have to add a few additional tags at the class level to provide all of the needed information. It should be noted that the additional tags will vary based on the view-type attribute specified earlier. The next tag encountered is called @ejb.pk with an attribute of . You can probably guest that this tag is used to indicate the type for the primary key defined in our database table. In this case, the class is int. Next, we define the characteristics of the home interface for our EJB as designated by the @ejb.home tag. For our example, we have only two attributes. The first attribute is generate="local", indicating the code generator should generate only a local home interface. The local-class="database.CommentHome" attribute tells the generator to output local home into the class CommentHome. We also have a tag called @ejb.interface that indicates the type of interface to generate. Again we have only two attributes that closely match those found in the @ejb.home tag. The generate attribute is the same as before, but the localclass="database.Comment" attribute specifies the class to output the interface. All of the tags just encountered set up the XDoclet generator along with the ejbdoclet and the Resin-specific doclet to output various files for our entity bean. We have placed all of the tags in the implementation file in order to keep the tags necessary for our bean in direct relationship with the implementation. Now we need to discuss the tags used within the implementation to define the set/get methods necessary for any entity bean. First notice there are set/get methods for each of the columns in our database table. The only exception is the ID column. Notice there is only a get method for this column. The reason is the ID is autogenerated by the database when new rows are added to the table. Since we will not be manually setting the ID, we don't want to include a set method. For each of the set methods, you will see a consistent pattern of tags. These are:

@ejb.persistent-field @ejb.interface-method


The @ejb.persistent-field tag tells the code generator that this field is persistent, and appropriate code needs to be generated to handle the persistence. The @ejb.interface-method instructs how the method will be exposed. The choices are local, remote, and both. You will also notice that the getlDO method includes a tag called @ejb.pk-field to indicate which of the fields is the primary key. In the case of the get methods, there is just the single @ejb.interface-method tag to indicate the exposure level of the method. There really isn't any more code needed in order for our entity bean to be automatically created by XDoclet. The only thing left to do is build an appropriate build.xml Ant build file.

Sample Ant Build File

Earlier in the chapter we discussed how an Ant task is needed to invoke the XDoclet code generation. The following listing is a complete build.xml script which will take our implementation file and build our entity bean.

<project default="all>
<property name="xdoclet.root.dir" value="c:\xdoclet-1.2"/>
<target >
<taskdef 
classname="xdoclet.modules. ejb.EjbDocletTask" classpathref="xdoclet. lib.path"/> </target>
<target depends="xdoclet">
<ejbdoclet destdir="ejbcode"> <fileset dir="ejbsrc">
<include name="* */*Bean.java"/> </fileset>
<deploymentdescriptor destdir="deployment"/>
<homeinterface /> <localinterface /> <localhomeinterface />
</ejbdoclet>
</target>
<target >
<mkdir dir=" {dest}"/> <javac srcdir="${ src }"
classpathref="resinclasspath"
destdir=" {dest}"
</target>
<target depends="xdoclet, generateEJB, build"/> </project>


As you can see there is quite a bit of additional information in a full build.xml build script. Let's start at the end of the file where we have a <target> element defined that depends on the xdoclet, generateEJB, and build targets. Look up at the top of the file, where the clean and xdoclet targets are defined. The xdoclet target will set up the environment needed to access the base XDoclet jars and classes. After the xdoclet target is accomplished, the generateEJB target will fire to handle all of our XDoclet code generation. The generateEJB task does almost all of the work by setting various environment variables and then executing several subtasks. Once the XDoclet and Resin class have done their work, the code for the entity bean will have been produced and it will be built.


JaVa
   
Comments