EJB CMP/CMR example with JBoss+Xdoclet
An abstract example
As said before, using Xdoclet, we merely have to focus on the implementation of our beans, and let Xdoclet generate all the necessary interface classes and deployment descriptors for us.
Consequently, the files involved in a (unidirectional) one-to-one CMR are
Table2Bean.java. In the concrete example section, we will also take a closer look at the generated
ejb-jar.xml file contains elements that describe relationships and navigability. The
jbosscmp-jdbc.xml contains the details of mapping to a database, hence are application server (container) specific.)
I’ll omit discussing the
build.xml which is supposed to deploy your beans and the
xdoclet.xml, which invokes Xdoclet to generate the necessary sources from the source+Xdoclet tags. (also known as
ejb-generate.xml, see this post). In my case these are taken care of by Eclipse, but you’re supposed to be acquainted enough with these files for your own favourite IDE or command line interface, otherwise this long post would be even longer.
Let’s get down to business. Suppose
Table1Bean wants to (unidirectionally one-to-one) refer to
To make this possible
Table1Beanmust have at least a primary key field
table1IDwith associated database column
table1_id VARCHAR(of course, any simple (not compound in CMR fields!!) type primary key definition will do), and
Table2Beanmust at least have a foreign key field
table1IDfkwith associated database column
I’ll assume you can set-up the entity beans without relations (if not, I’ll recommed this tutorial once more).
Now you have to add Xdoclet tags for establishing the (unidirectional one-to-one) relation for
- the bean deployment descriptor,
ejb-jar.xml, using the
- the (JBoss) application server, using the and
You have to add these tags to the comment section of the definition of the getter of your CMR field, so in
/** * ...omitted normal method comments with @return stuff etc... * * @ejb.interface-method * * @ejb.relation * name="table1-refers-to-table2" * role-name="Table1ToTable2" * cascade-delete="yes" * target-cascade-delete="yes" * target-role-name="Table2ToTable1" * target-ejb="Table2" * * @jboss.target-relation * related-pk-field="table1ID" * fk-column="table1_id_fk" */ public abstract ArticleLocal getArticle();
It is not necessary to use the
@ejb.ejb-ref class scope tags, you use these in e.g. your facade stateless session beans.
Now look very good what’s happening here. It took me a lot of time to figure out! Since we have unidirectionality here (the “blind side” in the EJB Xdoclet tag documentation is the side that is referred to in the unidirectional case), we have to specify the target side with the
target-rolename field. Not complying with this rule will result in deployment errors. The
target-ejb is compulsory (of course).
@jboss.target-relation has a field designating the primary key field of the originating bean (
related-pk-field) and a field designating the foreign-key database column of the referred to bean,
fk-column). Finally the
cascade-delete means that the associated bean is deleted, once the main bean is. This ensures referential integrity.
In our concrete example we’ll look at the resulting
Now upon creation of a
Table1Bean item (consisting of fields in
Table2Bean), we must
- Create an instance of
- Create an instance of
- Make a link/reference from
Table2Beanusing the CMR field.
According to the EJB 2.x spec, the CMR field can only be set in the
ejbPostCreate() method! This method must have the same signature as the
ejbCreate() method, of course.
Using the CMR field associated get-method, you are able to retrieve a reference to
Table2Bean. Looking ahead to one-to-many relation ships, we can already see that this get-method will return a Collection, instead of a reference to a single bean.
With these ingredients, you should be able to finish your application.
Finally, I want to stress once more that besides the JBoss tags in Xdoclet, there are corresponding tags for all kinds of application servers, such as JOnAS, Bea’s Weblogic and many more.