Mastering Enterprise JavaBeans™ and the Java 2 Platform, Enterprise Edition - Roman E.
.pdf
J2EE in the Real World: Implementing Our E- Commerce Entity Beans 
381
public void ejbCreate(String orderLineItemID, Order order, Product product, int quantity, double discount) throws CreateException, RemoteException {
System.out.println("OrderLineItem.ejbCreate(" + orderLineItemID + ", " + product.getName() + ", " + quantity + ") called");
this.orderLineItemID = orderLineItemID;
this.product = product;
productPK = ((ProductPK)product.getPrimaryKey()).productID;
this.order = order;
orderPK = ((OrderPK)order.getPrimaryKey()).orderID;
this.quantity = quantity; this.discount = discount;
}
/**
*The Container calls this after ejbCreate().
*At this point in time, the bean instance is
*associated with its own EJB Object. You can
*get a reference to that EJB Object by querying
*the context. You'd use that EJB Object
*reference when calling an external module, and
*you'd like to pass a reference to yourself.
*/
public void ejbPostCreate(String orderLineItemID, Order order, Product product, int quantity, double discount) throws CreateException, RemoteException { System.out.println("OrderLineItem.ejbPostCreate() called");
}
/**
*Called before the container removes entity
*bean data from the database. Corresponds to
*when client calls home.remove().
*/
public void ejbRemove() throws RemoteException { System.out.println("OrderLineItem.ejbRemove() called.");
//NOTE: We do not remove the Product because the Product
//can be reused over and over again for different line
//items. Similarly, we do not remove the Order because
//deleting a single line item should not delete an
//entire Order.
}
// No finder methods - they are implemented by Container
Source 13.6 OrderLineItemBean.java (continues).
Go back to the first page for a quick link to buy this book online!
382 
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
//------------------------------------------------
// End EJB-required methods //------------------------------------------------
}
Source 13.6 OrderLineItemBean.java (continued).
Handling Entity Bean References
The careful reader will notice that our Order Line Item bean makes use of our Product entity bean from Chapter 9. But our bean keeps two different pieces of information: a reference to a Product EJB object and that Product’s primary key. Why do we have both?
Let’s say you have an entity bean called FooBean, which references an EJB object of a separate entity bean called Bar:
public class FooBean implements EntityBean {
public Bar bar;
// ...
}
The field bar is a container-managed entity bean field. In EJB 1.0, an EJB container performing container-managed persistence is not required to transparently persist this reference.
This restriction has implications on our code. In our Order Line Item code, we reference a Product entity bean EJB object. We need to work with the EJB object because we need to call methods on our Product. An example of this is in the getBasePrice() method:
return quantity * product.getBasePrice();
But when our container persists our Order Line Item, we want to persist the Product reference as well. Because this is not transparent in EJB, we need to have the following code in ejbStore():
productPK = ((ProductPK)product.getPrimaryKey()).productID;
This converts the EJB object into its primary key, which is a container-managed field and will be persisted.
We also need to perform the opposite steps in ejbLoad() by converting the primary key back into an EJB object:
Go back to the first page for a quick link to buy this book online!
J2EE in the Real World: Implementing Our E- Commerce Entity Beans 
383
Context initCtx = new InitialContext(ctx.getEnvironment());
ProductHome productHome =
(ProductHome)initCtx.lookup("Ecommerce.ProductHome");
product = productHome.findByPrimaryKey(new OrderPK(orderPK));
This performs JNDI initialization and then looks up the EJB object based on the primary key that the container retrieved from the database.
In general, when your bean references another entity bean, you as a bean developer must construct and reconstruct your references in the following ways:
1.In the bean’s ejbStore() implementation, you must convert the EJB object into a primary key and let the EJB container persist the primary key.
2.In the bean’s ejbLoad() implementation, the bean developer must perform JNDI initialization, find a home object, and then perform a findByPrimaryKey() to reconstruct the EJB object reference.
A related issue arises in our bean’s ejbRemove() method. ejbRemove() is called on behalf of a client who wishes to remove this entity bean from the database. But our entity bean is holding a reference to a Product bean as well—should we remove the Product? The answer is no. Products are created once and are reusable over and over again in many quotes in a read-only fashion. It makes no sense to delete the Product when we remove this Order Line Item. This is the concept of aggregation in the Unified Modeling Language (UML): Deleting the owner object does not delete the subobject. Composition is the opposite: Deleting the owner object deletes all subobjects. We need to programmatically hard-code these relationships into our Java code.
Needless to say, this does not promote rapid application development very well. Performing steps such as converting and unconverting primary keys, manually deleting subobjects, and more are quite cumbersome and can easily be taken care of by the container, assuming you supply properties that go with your beans that describe your needs. And there is good news—some EJB containers transparently handle relationships between beans for you. But unfortunately, this is currently a proprietary feature that only some EJB container vendors provide. This leaves your beans as nonportable and increases your affinity to a single application server vendor. The EJB 2.0 specification promises to mandate standard relationship services. This will be a welcome addition, as almost any largescale deployment needs this functionality.
OrderLineItemHome.java
Our home interface defines ways to create and find our Order Line Items. The code is in OrderLineItem.java, listed in Source 13.7.
Go back to the first page for a quick link to buy this book online!
384 
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
We define one simple create method for creating a new Order Line Item and the required findbyPrimaryKey() method to look up existing line items by their ID.
package com.wiley.compBooks.ecommerce;
import javax.ejb.*;
import java.rmi.RemoteException; import java.util.Enumeration;
/**
*This is the home interface for OrderLineItem. The
*container implements this interface; the
*implementation object is called the Home Object
*and serves as a factory for EJB Objects.
*/
public interface OrderLineItemHome 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 orderLineItemID The line item's unique ID
*@param product The product this line item represents
*@param quantity The quantity of product in this line item
*@param discount The discount the customer receives
*
* @return The newly created EJB Object. */
public OrderLineItem create(String orderLineItemID, Order order, Product product, int quantity, double discount) throws CreateException, RemoteException;
/*
* Finder methods. Locate existing entity bean data. */
public OrderLineItem findByPrimaryKey(OrderLineItemPK key) throws FinderException, RemoteException;
public Enumeration findByOrder(String orderID) throws FinderException, RemoteException;
}
Source 13.7 OrderLineItemHome.java.
Go back to the first page for a quick link to buy this book online!
J2EE in the Real World: Implementing Our E- Commerce Entity Beans 
385
OrderLineItemPK.java
Finally, we have the primary key class for our Order Line Item, as shown in Source 13.8.
Our primary key class’s public fields must come from the container-managed fields of the bean. We select the ID of the order to encompass our primary key.
package com.wiley.compBooks.ecommerce;
import java.io.Serializable;
/**
*Primary Key class for our OrderLineItem
*Container-Managed Persistent Entity Bean */
public class OrderLineItemPK implements java.io.Serializable {
/*
*These are the primary key fields. They must be a
*subset of the bean's container-managed Bean fields.
*/
public String orderLineItemID;
public OrderLineItemPK(String orderLineItemID) { this.orderLineItemID = orderLineItemID;
}
public OrderLineItemPK() {
}
public String toString() {
return orderLineItemID.toString();
}
public int hashCode()
{
return orderLineItemID.hashCode();
}
public boolean equals(Object oli)
{
return ((OrderLineItemPK)oli).orderLineItemID.equals(orderLineItemID);
}
}
Source 13.8 OrderLineItemPK.java.
Go back to the first page for a quick link to buy this book online!
386 
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
The Deployment Descriptor
Our deployment descriptor will be inspected by the EJB container to discover information about our bean. It’s shown in Table 13.4.
Orders are mission-critical placements for goods, and they may be modified in a multiuser situation (consider a fulfillment application running concurrently with our e-commerce deployment). To ensure safety, we use the TRANSACTION_ SERIALIZABLE isolation level.
Next, we define a mapping for our container-managed fields to an underlying data store—currently a step that varies for each container. The field mapping is shown for the BEA WebLogic container in Table 13.5.
Table 13.4 Deployment Descriptor Settings for OrderLineItemBean
DEPLOYMENT
DESCRIPTOR SETTING |
VALUE |
Bean home name |
Ecommerce.OrderLineItemHome |
Enterprise bean class name |
com.wiley.compBooks.ecommerce.OrderLineItemBean |
Home interface class name |
com.wiley.compBooks.ecommerce.OrderLineItemHome |
Remote interface class name |
com.wiley.compBooks.ecommerce.OrderLineItem |
Environment properties |
see Table 13.7 |
Re-entrant |
false |
Primary key class name |
com.wiley.compBooks.ecommerce.OrderLineItemPK |
Container-managed fields |
orderLineItemID, productPK, quantity, and discount |
Transaction isolation level |
TRANSACTION_SERIALIZABLE |
Transaction attribute |
TX_REQUIRED |
Run-as mode |
CLIENT_IDENTITY |
|
|
Table 13.5 Persistent Settings for Our OrderLineItem Bean Assuming the BEA WebLogic Container
OBJECT/RELATIONAL SETTING
(ENTITY BEAN FIELD = RELATIONAL COLUMN NAME)
orderLineItemID=id
productPK=productPK
quantity=quantity
discount=discount
Go back to the first page for a quick link to buy this book online!
J2EE in the Real World: Implementing Our E- Commerce Entity Beans 
387
Table 13.6 Finder Semantics for OrderLineItem Bean Assuming the BEA WebLogic Container
FINDER SCRIPTING SYNTAX
“findByOrder(java.lang.String orderID)”
“(= orderID $orderID)”
Table 13.7 Environment Properties for OrderLineItemBean
ENVIRONMENT PROPERTY SETTING |
VALUE |
java.naming.factory.initial |
“weblogic.jndi.TengahInitialContextFactory” |
java.naming.provider.url |
“t3://localhost:7001” |
We also enumerate the logic of the finder methods that the container should implement. Again, this is also EJB container–specific and is shown for the BEA WebLogic container in Table 13.6.
We also use a number of environment properties. They are shown in Table 13.7. Recall that our bean’s ejbLoad() method uses JNDI to reconstruct the referenced Product EJB object from its stored primary key. The environment properties are needed to perform this JNDI initialization.
The Order Entity Bean
Our last entity bean models an entire Order work request. Our Orders will contain the following information:
■■The unique ID of the Order
■■The Customer who placed the Order, so we know who to bill and where to ship our Order
■■The subtotal, taxes, and price of the Order
■■The date that the Order was placed
Let’s dive into the implementation and see how our Order bean works.
Order.java
Order.java, shown in Source 13.9, is our Order’s remote interface. It consists of a few get/set methods on the Order’s data fields.
Go back to the first page for a quick link to buy this book online!
388 
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.ecommerce;
import javax.ejb.*;
import java.rmi.RemoteException; import java.util.*;
/**
*These are the business logic methods exposed publicly
*by OrderBean.
*
*This interface is what clients operate on when they
*interact with beans. The container vendor will implement
*this interface; the implementation object is called the
*EJB Object, which delegates invocations to the actual bean. */
public interface Order extends EJBObject {
/**
*Returns the set of Order Line Items that compose
*this Order. Each Line Item represents a specific
*product and quantity ordered.
*/
public Enumeration getLineItems() throws RemoteException;
/**
* Returns the customer address set by setCustomer() */
public Customer getCustomer() throws RemoteException;
/**
*Returns the subtotal price that has been previously
*set by setSubtotal().
*/
public double getSubtotal() throws RemoteException;
/**
*Sets the subtotal price. The subtotal should be
*externally calculated from the line item base
*prices and adjusted based on customer discounts.
*/
public void setSubtotal(double subTotal) throws RemoteException;
/**
* Returns the taxes for this Order. */
public double getTaxes() throws RemoteException;
Source 13.9 Order.java (continues).
Go back to the first page for a quick link to buy this book online!
J2EE in the Real World: Implementing Our E- Commerce Entity Beans 
389
/**
* Sets the taxes for this Order. */
public void setTaxes(double taxes) throws RemoteException;
/**
*Returns the total price. Total Price is computed from:
*1) Subtotal price
*2) Tax
*/
public double getTotalPrice() throws RemoteException;
/**
*Retrieves the date this was ordered on. Date is set
*automatically when new Order is created.
*/
public Date getDate() throws RemoteException;
}
Source 13.9 Order.java (continued).
The date for the order will automatically be set on order creation, so there is no method to set the date. The total price is calculated from each line item, so that is not mutable by clients either.
OrderBean.java
Our Order’s implementation is in OrderBean.java, shown in Source 13.10.
The bean code should be fairly self-explanatory. Our ejbCreate() method is called when a new order is created. ejbCreate() initializes the bean’s fields to the passedin values. For example, we set the date field to be the current date. The container will persist our container-managed fields to the database for us after ejbCreate().
Notice how we’re using a java.sql.Timestamp for our date field. This is the JDBC analog to a date. We use this so that our dates will map well to a relational database date field. If you’d like to work with a regular java.util.Date, you can simply modify the ejbLoad() and ejbStore() methods to convert and unconvert from a java.sql.Timestamp to a java.util.Date.
As with the Order Line Item example, our bean is referencing external entity beans—specifically, we reference a Customer bean. Because we can’t persist EJB object references, our ejbStore() method must convert the EJB objects into primary keys in preparation for the container to save the fields. Our ejbLoad() method must do the opposite—convert the container-loaded primary keys back into EJB objects so we can use them again.
Go back to the first page for a quick link to buy this book online!
390 
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.ecommerce;
import java.util.*; import java.io.*; import java.rmi.*;
import javax.naming.*; import javax.ejb.*;
/**
*This is a container-managed persistent entity bean that
*represents an order placed for goods.
*
*Note: This Bean could easily be extended to include other
*things, such as:
*- Shipping charges
*- Shipping address vs. Billing address
*- A date that this order is scheduled to be completed/shipped.
*- Status information about the order. This could be set by a
*Fulfillment component to different status levels, such as
*"manufacturing" or "shipping" or "delivered".
*/
public class OrderBean implements EntityBean {
protected EntityContext ctx;
//------------------------------------------------------
// Begin Container-Managed fields //------------------------------------------------------
/*
*This order's identification number. It's also our
*Primary Key.
*/
public String orderID;
/*
*The Customer who placed this Order. Customer
*information is encapsulated in a separate bean,
*called CustomerBean, with an EJB Object called
*Customer.
*Unfortunately, EJB 1.0 does not mandate that
*Containers persist references to EJB Objects. We
*must persist this Customer field as a serializable
*primary key, rather than an EJB Object. Yet we
*still want to work with an EJB Object so that we can
*call methods on it. Hence, we must keep two fields:
Source 13.10 OrderBean.java (continues).
Go back to the first page for a quick link to buy this book online!
