| Sign In/My Account | View Cart |
EJB 2.0 finally gives us a Container-Managed Persistence (CMP) model to work with. Whenever possible, I like to use CMP beans in my EJB projects; however, for the odd thing, I need to change my entity to be bean-managed. I use the following pattern to allow me to go from a CMP model to a Bean-Managed Persistence (BMP) model in a clean way.
In this article, we will discuss:
When EJB first came out, it got a real hammering over CMP. When EJB 2.0 came out, along came a revamped CMP model, giving us features we really wanted like relationships and standardizing on a query language.
When it comes to writing a CMP bean, we do so in a very different way, compared to doing so with EJB 1.1. We create an abstract class, and instead of creating public fields for the managed variables, we create abstract getters and setters (like JavaBeans). This allows the vendor persistence manager to implement the accessors to the data in their own way.
This helps them put in logic that says things like:
ejbStore().SET that field in the UPDATE query.get method.Side Question: Why do we have to create abstract methods in this abstract class? Why can't the persistence manager just create the methods in the subclass?
Answer: We need to access these methods in the abstract class. For example, in ejbCreate(...), we go through the passed-in arguments and set*() them.
To show this entity pattern, we will look at a simple application that models an inventory system. The parts of the application are:
inventory, which holds the item name (primary key), price, and the number of items in stock.One key point is that when we migrate the inventory entity bean from CMP to a BMP implementation, nothing else will change.
Let's look at implementing the inventory entity bean using CMP.
The inventory CMP requires us to create an abstract class (compliant to the Entity spec), and XML descriptor files telling the mapping framework what to map. Figure 1 shows what these items look like.
|
|
The abstract entity has the following properties:
Implements javax.ejb.EntityBean.
abstract public class InventoryBean implements EntityBean {.
Implements methods declared in EntityBean interface:
public void setEntityContext(EntityContext context) {
ctx = context;
}
public void unsetEntityContext() {
ctx = null;
}
public void ejbActivate() {}
public void ejbPassivate() {}
public void ejbRemove() throws RemoveException {}
public void ejbStore() {}
public void ejbLoad() {}
Implements an ejbCreate() and an ejbPostCreate() method that corresponds to the create() method in the home interface (uses abstract set methods to set all incoming params):
public String ejbCreate(String item, float price, int stock) throws CreateException {
setItem(item);
setPrice(price);
setStock(stock);
return null;
}
public void ejbPostCreate(String item, float price, int stock) throws CreateException {}
Implements the abstract get and set methods:
public abstract String getItem();
public abstract void setItem(String item);
public abstract float getPrice();
public abstract void setPrice(float price);
public abstract int getStock();
public abstract void setStock(int stock);
Implements a helper method to get access to the entity context (this will be used in the BMP bean later):
public EntityContext getEntityContext() {
return ctx;
}
We have created a CMP-compliant entity bean class, and now it's time to create the deployment descriptors. First we create the "standard" ejb-jar.xml, and then we need to configure the vendor-specific information. We will show the WebLogic 6.1 deployment descriptors because we have to pick one.
Configure basic entity information:
We configure the class names, using the "local" variants, which means that these are local entity beans. We tell the container that this entity is CMP via the persistence-type XML tag.
<entity>
<ejb-name>InventoryBean</ejb-name>
<local-home>InventoryHome</local-home>
<local>Inventory>/local<
<ejb-class>InventoryBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
Next, we tell the container which fields are to be managed, and that the item is the primary key:
<cmp-field>
<field-name>item</field-name>
</cmp-field>
<cmp-field>
<field-name>price</field-name>
</cmp-field>
<cmp-field>
<field-name>stock</field-name>
</cmp-field>
<primkey-field>item</primkey-field>
Finally, we configure the findAllPrices() method using EJB-QL:
<query>
<query-method>
<method-name>findAllPrices</method-name>
<method-params>
</method-params>
</query-method>
<ejb-ql><![CDATA[WHERE 1=1]]></ejb-ql>
</query>
Pages: 1, 2 |