|
|
|
When developing the presentation logic, we were
CartModel
OrderModel
InventoryModel
CustomerModel
Now that we have implemented our business logic as a set of EJBs, it is time to connect them to the model objects.
Since each model object will delegate onto an associated EJB, we will need code that enables the model object to look up the appropriate EJB home in JNDI. We will introduce a specific method in each model object for that purpose. The resulting home reference can be cached for later use. The
getShoppingCartHome()
method and
import javax.naming.InitialContext; import javax.ejb.EJBException; import java.util.Vector; public class CartModel { private final static String SHOPPINGCART_HOME_NAME = "java:comp/env/ejb/plantsby/ShoppingCartHome"; private static ShoppingCartHome shoppingCartHome; private ShoppingCartHome getShoppingCartHome() { if ( shoppingCartHome == null ) { try { InitialContext ctx= new InitialContext(); shoppingCartHome= (ShoppingCartHome) ctx.lookup(SHOPPINGCART_HOME_NAME); } catch (Exception e) { throw new EJBException(e); } return shoppingCartHome; } else { return shoppingCartHome; } } }
Each model object will have similar JNDI lookup code for its own specific EJB home lookup.
Since a
CartModel
will delegate to exactly one
ShoppingCart
session bean, we can create the session bean in the
CartModel
constructor. The remaining
CartModel
private ShoppingCart shoppingCart; CartModel() { try { shoppingCart= getShoppingCartHome().create(); } catch (Exception e) { throw new EJBException(e); } } public void addItem(StoreItem si) { shoppingCart.addItem(si); } public Vector getItems() { return shoppingCart.getItems(); }
In doing the integration of the
InventoryModel
object with the
Inventory
EJB, we run into a little snafu. The presentation logic uses a
String
type for category, whereas the business logic uses an integer. We cannot possibly over-stress the importance of a
So let's add a method to map category strings to integers:
private int getCategoryKeyFromString(String category) { int icategory; if ( category.equals("flowers") ) { icategory = Inventory.FLOWERS; } else if ( category.equals("fruit") ) { icategory = Inventory.FRUIT; } else if ( category.equals("trees") ) { icategory = Inventory.TREES; } else if ( category.equals("accessories") ) { icategory = Inventory.ACCESSORIES; } else throw new EJBException("category not valid – category = " + category); return icategory; } }
The InventoryModel uses the StoreItem class to represent inventory items, so that it does not expose the Inventory EJB interface. That means will need additional helper classes to convert an Inventory collection to StoreItem s:
private StoreItem InventoryToStoreItem(Inventory inv) { return new StoreItem(inv); } private Collection InventoryToStoreItems(Collection c) { Vector v = new Vector(); try { Iterator i = c.iterator(); while ( i.hasNext() ) { Inventory inv = (Inventory) i.next (); v.add(InventoryToStoreItem(inv)); } return v; } catch (Exception e) { throw new EJBException(e); } }
The
InventoryModel
offers two finder methods, which do nothing more than delegate to
InventoryHome
public Collection findByCategory(String category) { try { int icategory = getCategoryKeyFromString(category); Collection c = getInventoryHome().findByCategory(icategory); return InventoryToStoreItems(c); } catch (Exception e) { throw new EJBException(e); } } public StoreItem findById(String id) { try { InventoryKey key = new InventoryKey(id); Inventory inv = (Inventory) getInventoryHome().findByPrimaryKey(key); return InventoryToStoreItem(inv); } catch (Exception e) { throw new EJBException(e); } }
and of course here's the EJB lookup:
private final static String INVENTORY_HOME_NAME= "java:comp/env/ejb/plantsby/InventoryHome"; private static InventoryHome inventoryHome; private InventoryHome getInventoryHome() { if ( inventoryHome == null ) { try { InitialContext ctx = new InitialContext(); inventoryHome = (InventoryHome) ctx.lookup(INVENTORY_HOME_NAME); } catch (Exception e) { e.printStackTrace(); throw new EJBException(e); } return inventoryHome; } else { return inventoryHome; } }
The OrderModel object has only a single business method, addOrder() , which is a simple delegation to the Order EJB. Note we have not implement supported for credit cards. We'll just fake it for now. Adding credit-card support is beyond what we'll cover in this chapter:
public String addOrder(CustomerInfo c, Vector orderItems) { try { Order o = getOrderHome().create(c.getEmail(), c.getName(), c.getAddr1(), c.getAddr2(), c.getCity(), c.getState(), c.getZipcode(), c.getPhone(), c.getName(), c.getAddr1(), c.getAddr2(), c.getCity(), c.getState(), c.getZipcode(), c.getPhone(), "NO CREDIT CARD", "NO CC NUMBER", "NO CC MONTH", "NO CC YEAR", "NO CARD HOLDER", 1, // shipping method orderItems); return o.getID(); } catch (Exception e) { throw new EJBException(e); } }
and the getOrderHome() method and support:
private final static String ORDER_HOME_NAME = "java:comp/env/ejb/plantsby/OrderHome"; private static OrderHome inventoryHome; private OrderHome getOrderHome() { if ( inventoryHome == null ) { try { InitialContext ctx= new InitialContext(); inventoryHome= (OrderHome) ctx.lookup(ORDER_HOME_NAME); } catch (Exception e) { e.printStackTrace(); throw new EJBException(e); } return inventoryHome; } else { return inventoryHome; } }
The customer model has two methods to implement: one to add a customer; one to find one. These methods will primarily use the
Customer
EJB's finder methods. The
addCustomer()
method is the exception: it uses the
Customer
method
update()
to update an existing
Customer
to account for changes the
public void addCustomer(CustomerInfo i) { CustomerKey key = new CustomerKey(i.getEmail()); try { Customer c = getCustomerHome().findByPrimaryKey(key); c.update( i.getFirstName(), i.getLastName(),i.getAddr1(), i.getAddr2(), i.getCity(), i.getState(), i.getZipcode(), i.getPhone() ); } catch ( FinderException e ) { try { Customer c = getCustomerHome().create(key, "PASSWORD", i.getFirstName(), i.getLastName(), i.getAddr1(), i.getAddr2(), i.getCity(), i.getState(),i.getZipcode(), i.getPhone()); } catch ( CreateException ex) { throw new EJBException("Could not create new customer"); } } } public CustomerInfo getCustomer(String emailKey) { CustomerKey key = new CustomerKey(emailKey); try { Customer c= getCustomerHome().findByPrimaryKey(key); CustomerInfo ci= new CustomerInfo(); ci.setEmail(c.getCustomerId()); ci.setFirstName(c.getFirstName()); ci.setLastName(c.getLastName()); ci.setAddr1(c.getAddr1()); ci.setAddr2(c.getAddr2()); ci.setCity(c.getCity()); ci.setState(c.getState()); ci.setZipcode(c.getZip()); ci.setPhone(c.getPhone()); return ci; } catch ( FinderException e ) { throw new EJBException("Could not find customer with key " + emailKey); } }
Finally, the EJB lookup:
private final static String Customer_HOME_NAME = "java:comp/env/ejb/plantsby/CustomerHome"; private static CustomerHome CustomerHome; private CustomerHome getCustomerHome() { if ( CustomerHome == null ) { try { InitialContext ctx = new InitialContext(); CustomerHome= (CustomerHome) ctx.lookup(Customer_HOME_NAME); } catch (Exception e) { e.printStackTrace(); throw new EJBException(e); } return CustomerHome; } else { return CustomerHome; } }
Finally, and as the last step in connecting our EJBs to the model beans in our web module, let's declare the EJB references we require in PlantsByWebSphereWAR . Do this by opening the Deployment Descriptor editor for the PlantsByWebSphereWAR . Select the Resources tab in the editor.
The screen layout is slightly different because it's a web module, but
Choose the EJB Local tab, click the Add button Complete the web module reference declarations based on the following table:
|
Name |
Local Home |
Local |
|---|---|---|
|
ejb/plantsby/ShoppingCartHome |
com.ibm.pbw.ejb.ShoppingCartHome |
com.ibm.pbw.ejb.ShoppingCart |
|
ejb/plantsby/InventoryHome |
com.ibm.pbw.ejb.InventoryHome |
com.ibm.pbw.ejb.Inventory |
|
ejb/plantsby/OrderHome |
com.ibm.pbw.ejb.OrderHome |
com.ibm.pbw.ejb.Order |
|
ejb/plantsby/CustomerHome |
com.ibm.pbw.ejb.CustomerHome |
com.ibm.pbw.ejb.Customer |
|
|
|