Mastering Enterprise JavaBeans™ and the Java 2 Platform, Enterprise Edition - Roman E
..pdfMETHOD |
EXPLANATION |
ejbPostCreate(<…>) |
There is one ejbPostCreate(...) |
|
for each ejbCreate(...). Each |
(new for container- |
pair has the same parameters. |
managed persistence) |
|
|
The container calls your bean |
|
instance’s ejbPostCreate(...) |
|
method following ejbCreate(...). |
TYPICAL IMPLEMENTATION
The container calls ejbPostCreate() after it has associated your bean instance with an EJB object. You can now complete your initialization, by doing anything you need to that requires that EJB object, such as passing your bean’s EJB object reference to other beans.
You might also use this method to reset certain transactionrelated parameters—for example, you could keep a data status flag in the bean to indicate whether a field has been changed. Because the bean instance may have been used before, these fields might have dirty data.
|
|
Note: By now the EJB container |
|
|
will have created your primary |
|
|
key object, so you can now |
|
|
retrieve it and use it. |
ejbActivate() |
When a client calls a business |
Acquire any bean-specific |
|
method on an EJB object, but |
resources, such as socket |
(same as bean- |
there is no entity bean instance |
connections, that your bean |
managed persistence) |
bound to the EJB object, the |
needs to service a particular |
|
container needs to take a bean |
client when it’s moved into the |
|
from the pool and transition it |
ready state. |
|
into a ready state. This is called |
|
|
activation. On activation, the |
|
|
ejbActivate() method is called |
|
|
by the EJB container. |
|
|
Note: ejbActivate() is never |
|
|
called during a transaction. |
|
ejbLoad() |
The EJB container calls this to |
Do not read data from the |
|
load database data into your |
database in this method. Rather, |
(new for container- |
bean instance, based on the |
the EJB container will read in |
Managed Persistence) |
current transactional state. |
data from the database for you |
|
|
automatically right before calling |
|
|
your ejbLoad() method. It does |
|
|
this by setting your container- |
|
|
managed fields to the data it |
|
|
reads from the database. |
|
|
In this method, you should per- |
|
|
form any utilities you need to |
|
|
work with the read-in data, such |
|
|
as decompressing a text field. |
|
|
continues |
239
240 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
Table 9.1 (Continued)
METHOD |
EXPLANATION |
ejbStore() |
The EJB container calls this to |
|
update the database to the |
(new for container- |
new values of your in-memory |
managed persistence) |
fields, thus synchronizing the |
|
database. The current transac- |
|
tional state dictates when this |
|
method is called. Also, this |
|
method is called during passiv- |
|
ation, directly before |
|
ejbPassivate(). |
TYPICAL IMPLEMENTATION
Do not update the database in this method. Rather, the EJB container will update the database for you automatically right after calling your ejbStore() method. It does this by extracting your container-managed fields and writing them to the database.
In this method, you should prepare your container-managed fields to be written to the database. For example, you can compress the text of your fields if necessary.
ejbPassivate() |
The EJB container will call this |
Release any resources, such as |
|
method when it wants to return |
socket connections, that you |
(same as bean- |
your entity bean to the pool. |
allocated in ejbActivate() and |
managed persistence) |
This is called passivation and |
that your bean was holding |
|
is the opposite of activation. On |
during the ready state for a |
|
passivation, the ejbPassivate() |
particular client. |
|
method is called by the EJB |
|
|
container. |
|
|
Note: ejbPassivate() is never |
|
|
called during a transaction. |
|
ejbRemove() |
The client calls the home |
Do not destroy database data in |
|
object’s remove() method to |
this method. Rather, simply |
(new for container- |
destroy database data |
perform any operations that |
managed persistence) |
remove(), which then calls |
must be done before the data in |
|
your ejbRemove(). Note that |
the database is destroyed. The |
|
this does not destroy the Java |
EJB container will destroy the |
|
Object because the object can |
data for you right after |
|
be pooled and reused for |
ejbRemove() is called. |
|
different data. |
|
unsetEntityContext() |
This method disassociates a |
|
bean from its environment. |
(same as bean- |
The container calls this right |
managed persistence) |
before your entity bean |
|
instance is destroyed (when it |
|
wants to reduce the pool size). |
Release any resources you allocated during setEntityContext(), and get ready to be garbage collected.
Go back to the first page for a quick link to buy this book online!
Writing Container-Managed Persistent Entity Beans 241
Container-Managed Persistence Example:
A Product Line
Let’s see a quick demonstration of container-managed persistence in action, applied to the concept of a product line.
If you’re working for a product-based company, your company’s product line is the suite of products your company offers. For example, if you’re an appliance company, you might offer a dishwasher, a stove, and a dryer. If you’re a computer hardware company, you might offer memory, hard disks, and processors. We’re going to model a generic product as an entity bean that uses containermanaged persistence.
The object model for our product line is detailed in Figure 9.1.
|
<<interface>> |
|
<<interface>> |
|
|
java.rmi.Remote |
|
java.io.Serializable |
|
|
|
Comes with Java 2 platform |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
<<interface>>
javax.ejb.EnterpriseBean
<<interface>> <<interface>> javax.ejb.EJBObject javax.ejb.EJBHome
<<interface>>
javax.ejb.EntityBean
Comes with EJB distribution
<<interface>> |
|
<<interface>> |
|
Product Bean |
|
Product |
Product |
|
Product |
|
Implementation |
|
|
|
|
|
Primary Key Class |
|||
Remote Interface |
|
Home Interface |
|
Class |
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
Suppplied by Bean provider (we will write)
Product |
|
Product |
EJB Object |
|
Home Object |
|
|
|
Generated for us by container vendor's tools
Figure 9.1 The object model for our product line.
Go back to the first page for a quick link to buy this book online!
242 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
Let’s take a look at each of the files that we must create for our entity bean component.
Product.java
Our remote interface is specified by Product.java, shown in Source 9.1.
Our remote interface is very similar to Chapter 8’s bank account remote interface. It has methods to modify the entity bean instance’s fields and throws remote exceptions to indicate system-level errors.
ProductHome.java
Next, we have the product’s home interface, ProductHome.java, presented in Source 9.2.
package com.wiley.compBooks.roman.entity.product;
import javax.ejb.*;
import java.rmi.RemoteException;
/**
*These are the public business methods of ProductBean.
*This interface is what clients operate on when they
*interact with beans. The EJB Server vendor will
*implement this interface; the implemented object instance
*is called the EJB Object, which delegates invocations to
*instances of the ProductBean class.
*/
public interface Product extends EJBObject {
// Getter/setter methods for Entity Bean fields
public String getName() throws RemoteException;
public void setName(String name) throws RemoteException;
public String getDescription() throws RemoteException;
public void setDescription(String description) throws RemoteException;
public double getBasePrice() throws RemoteException;
public void setBasePrice(double price) throws RemoteException;
public String getProductID() throws RemoteException;
}
Source 9.1 Product.java.
Go back to the first page for a quick link to buy this book online!
Writing Container-Managed Persistent Entity Beans 243
package com.wiley.compBooks.roman.entity.product;
import javax.ejb.*;
import java.rmi.RemoteException; import java.util.Enumeration;
/**
*This is the home interface for Product. This interface
*is implemented by the EJB Server's glue-code tools.
*The implemented object is called the Home Object and
*serves as a factory for EJB Objects.
*
*One create() method is in this Home Interface, which
*corresponds to the ejbCreate() method in the Product file. */
public interface ProductHome extends EJBHome {
/*
*This method creates the EJB Object.
*Notice that the Home Interface returns an EJB Object,
*whereas the Bean returns void. This is because the
*EJB Container is responsible for generating the EJB
*Object, whereas the Bean is responsible for
*initialization.
*
*@param productID The number of the product (unique)
*@param name The name of the product
*@param description Product description
*@param basePrice Base Price of product
*
* @return The newly created EJB Object. */
Product create(String productID, String name, String description, double basePrice) throws CreateException, RemoteException;
//Finder methods. These are implemented by the
//container. You can customize the functionality of
//these methods by using the EJB Container tools.
public Product findByPrimaryKey(ProductPK key) throws FinderException, RemoteException;
public Enumeration findByName(String name) throws FinderException, RemoteException;
public Enumeration findByDescription(String description) throws FinderException, RemoteException;
Source 9.2 ProductHome.java (continues).
Go back to the first page for a quick link to buy this book online!
244 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
public Enumeration findByBasePrice(double basePrice) throws FinderException, RemoteException;
public Enumeration findExpensiveProducts(double minPrice) throws FinderException, RemoteException;
public Enumeration findCheapProducts(double maxPrice) throws FinderException, RemoteException;
public Enumeration findAllProducts() throws FinderException, RemoteException;
}
Source 9.2 ProductHome.java (continued).
Our home interface defines a single create() method to create a new product in the database. It returns a Product EJB object so the client can manipulate the entity bean data and throws a javax.ejb.CreateException to indicate an appli- cation-level problem.
We also expose all sorts of finder methods to find existing products. Some of the finders return a single EJB object, while others return a java.util.Enumeration of multiple EJB objects. This is needed if the finder methods find more than one matching object. Note that findByPrimaryKey() should never return an enumeration because primary keys must be unique.
ProductPK.java
Our primary key class is defined by ProductPK.java, shown in Source 9.3.
As with our Bank Account, our primary key is a simple string. And as we’ve found out, there are restrictions for what our primary key can be. Our primary key fields are coming from the container-managed fields of the entity bean class, as is required with container-managed persistence. In particular, our primary key represents the ID string of a product (such as a product SKU number).
ProductBean.java
Next, we have our container-managed entity bean implementation, ProductBean
.java, shown in Source 9.4.
This bean is more complex than our bank account example. We’ve defined many finder methods, and we have four persistent fields. Yet even though we’ve added all this complexity, our bean is less than 40 percent of the size of our Bank Account
Go back to the first page for a quick link to buy this book online!
Writing Container-Managed Persistent Entity Beans 245
package com.wiley.compBooks.roman.entity.product;
import java.io.Serializable;
/**
*Primary Key class for our 'Product' Container-Managed
*Entity Bean
*/
public class ProductPK implements java.io.Serializable {
/*
*Note that the primary key fields must be a
*subset of the the container-managed Bean fields.
*The fields we are marking as container-managed in
*our Bean are productID, name, desc, and basePrice.
*Therefore our PK fields need to be from that set.
*/
public String productID;
public ProductPK(String productID) { this.productID = productID;
}
public ProductPK() {
}
public String toString() { return productID.toString();
}
}
Source 9.3 ProductPK.java.
bean. This is an amazing reduction in code complexity. And because our bean has no database code in it, we have reduced the chance for bugs in our bean that would be due to user error working with JDBC code. This is a huge savings in development and testing time.
We have four container-managed fields, all with public scope. They’re public so that the container can manipulate them. Our ejbCreate() method simply sets our container-managed fields to the passed-in client parameters. The EJB container will extract those fields and set up the database data for us. Notice that our ejbCreate() method does not return a primary key because the EJB container does that for us.
The rest of our bean is just empty methods and comments. There’s almost no logic at all. Our bean class is just data with some accessor methods.
Go back to the first page for a quick link to buy this book online!
246 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
package com.wiley.compBooks.roman.entity.product;
import java.sql.*; import javax.naming.*; import javax.ejb.*; import java.util.*;
import java.rmi.RemoteException;
/**
*Entity Bean that demonstrates Container-Managed persistence.
*This is a product that's persistent. It has an ID #, a name,
*a description, and a base price.
*/
public class ProductBean implements EntityBean {
protected EntityContext ctx;
//Container-managed state fields. Note that they must
//be public.
public String |
productID; |
// PK |
|
public |
String |
name; |
|
public |
String |
description; |
|
public double basePrice;
public ProductBean() {
System.out.println("New Product Entity Bean Java Object created by EJB Container.");
}
//
//Business Logic Methods
//Simple getter/setter methods of Entity Bean fields.
public String getName() throws RemoteException { System.out.println("getName() called."); return name;
}
public void setName(String name) throws RemoteException { System.out.println("getName() called.");
this.name = name;
}
public String getDescription() throws RemoteException { System.out.println("getDescription() called.");
Source 9.4 ProductBean.java (continues).
Go back to the first page for a quick link to buy this book online!
Writing Container-Managed Persistent Entity Beans 247
return description;
}
public void setDescription(String description) throws RemoteException { System.out.println("setDescription() called.");
this.description = description;
}
public double getBasePrice() throws RemoteException { System.out.println("getBasePrice() called."); return basePrice;
}
public void setBasePrice(double price) throws RemoteException { System.out.println("setBasePrice() called."); this.basePrice = price;
}
public String getProductID() { System.out.println("getProductID() called."); return productID;
}
//
// EJB-required methods
//
/**
*Called by Container.
*Implementation can acquire needed resources.
*/
public void ejbActivate() throws RemoteException { System.out.println("ejbActivate() called.");
}
/**
*EJB Container calls this method right before it
*removes the Entity Bean from the database.
*Corresponds to when client calls home.remove().
*/
public void ejbRemove() throws RemoteException { System.out.println("ejbRemove() called.");
}
/**
*Called by Container.
*Releases held resources for passivation.
*/
Source 9.4 ProductBean.java (continues).
Go back to the first page for a quick link to buy this book online!
248 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
public void ejbPassivate() throws RemoteException { System.out.println("ejbPassivate () called.");
}
/**
*Called from the Container. Updates the entity bean
*instance to reflect the current value stored in
*the database.
*Because we're using Container-Managed Persistence, we
*can leave this method blank. The EJB Container will
*automatically set our public fields to the correct values.
*/
public void ejbLoad() throws RemoteException { System.out.println("ejbLoad() called.");
}
/**
*Called from the Container. Updates the database to
*reflect the current values of this in-memory Entity Bean
*instance representation.
*Because we're using Container-Managed Persistence, we can
*leave this method blank. The EJB Container will
*automatically save our public fields into the database.
*/
public void ejbStore() throws RemoteException {
System.out.println("ejbStore() called.");
}
/**
*Called by Container. Associates this Bean instance with
*a particular context. Once done, we can query the
*Context for environment info, such as Bean customizations
*via properties.
*/
public void setEntityContext(EntityContext ctx) throws RemoteException { System.out.println("setEntityContext called");
this.ctx = ctx;
}
/**
*Called by Container. Disassociates this Bean instance
*with a particular context environment.
*/
public void unsetEntityContext() throws RemoteException {
Source 9.4 ProductBean.java (continues).
Go back to the first page for a quick link to buy this book online!