Chapter 19: Session Beans and Business Logic

Download Report

Transcript Chapter 19: Session Beans and Business Logic

Session Beans & Business Logic
CS 486
Sagar Deshpande
Requirements
1.
2.
3.
4.
5.
6.
The Engineering Dept needs to be able to define a product as series of steps
that manufacturing facility will follow to build it
Should be able to accept from web as well as from phone operators who get
orders from Sales personnel. Notify Manufacturing dept that a particular is
placed and must be delivered on a particular due date. The identifier to this
order is a unique sales division and a number provided by sales division.
Duplicate order numbers exist between sales division.
Should be able to cancel orders on which manufacturing has not started, and
prevent cancellation of order on which work has started
Manufacturing dept should be able to select a order based on due date and
time it has to be in inventory before delivering
Management should be able retrieve a list of overdue orders
Manufacturing dept should notify shipping dept if a shipment is read, indicate
carrier appropriate for the size and weight and loading dock where the
product is sent.
Two session Beans
ManageOrders --stateless
Manufacture --stateful
Two entity beans
Product
Order
Implementation
ManageOrders , a stateless session bean used to manage orders, which also has a utility
function to create sample products









Package factory.manage_orders consisting of
ManageOrders (remote interface)
ManageOrdersHome (Home interface)
ManageOrdersEJB
DuplicateOrderException
NoSuchOrderException
NoSuchProductException
OpenOrderView
OverdueOrderView
ProductCreationHelper// helper class
A stateful session bean Manufacture used to control manufacturing process
factory.manufacture package consisting of

Manufacture(remote interface)

ManufactureHome(home interface)

ManufactureEJB
Remote Interface for ManageOrders stateless session bean
package factory.manage_orders;
import javax.ejb.*;
import java.util.Date;
import java.rmi.RemoteException;
import factory.order.OrderNotCancelableException;
public interface ManageOrders extends EJBObject{
void placeOrder(int salesDivision, int orderNumber, String product, Date datedue) throws
RemoteException, NoSuchProductException, DuplicateOrderException;
void cancelOrder(int salesDivision, int orderNumber) throws RemoteException,
orderNotCancelableException, NosuchOrderException;
OverdueOrderView[] getOverdueOrders() throws RemoteException;
OpenOrderView[] getSchedulableOrders() throws RemoteException
void createProduct(String id, String name) throws RemoteException
void createSampleProducts() throws RemoteException //utitlityfunction
void addRoutingInstruction(String id, int sequence , String instruction) throws
RemoteException
In the above interface, in a few methods salesDivision and ordernumber form a unique
combination to identify any order.
Two methods getOverdueorders() and getSchedulabeorders() return arrays of objects
The other way to implement this to implement java.sql.Resultset interface or
java.sql.RowSet Interface with info provided in rows and columns
Here the assumption is result set is manageable,what if not ?
Typical to arbitrary search criteria
Depends on specifics of application
Send a chunk , ask for refinement
Get a marker from client , send data in chunks, this is possible because connections to
database are pooled,hence no burden of creating connections.
Another issue to be addressed
How to transfer data about a single entity from server to client
getEachParameter() increases network traffic
Use a structure, with serializable parameter and pass it.
Problem with this
Specific to particular type of client, introducing coupling between
client and server
Use java.sql.resultset
What if data not tabled
Use java.util.map-using a Key-value pair
Implementing exception classes
package factory.manage_orders;
Public class DuplicateOrderException extends Exception{
public DuplicateOrderException()
}
package factory.manage_orders;
public class NoSuchProductException extends Exception{
public NoSuchProductException()
}
Implementing OpenOrderView class
package factory.manage_orders;
import java.io.Serializable;
import java.util.Date;
public class OpenOrderView implements Serializable{
public final int salesDivision
public final int orderNumber
public final String product;
public final Date datedue;
public OpenOrderView(int salesDivision, int orderNumber,String product, Date datedue){
this.salesDivision=salesDivision;
this.orderNumber=orderNumber;
this.product=product;
this.datedue=datedue;
}
}
Implementing OverdueOrderView class
package factory.manage_orders;
import java.io.Serializable;
import java.util.Date;
public class OverdueOrderView implements Serializable{
public final int salesDivision
public final int orderNumber
public final String product;
public final Date datedue;
public OverdueOrderView(int salesDivision, int orderNumber,String product, String status,
Date datedue){
this.salesDivision=salesDivision;
this.orderNumber=orderNumber;
this.product=product;
this.status=status;
this.datedue=datedue;
}
}
Home interface for manage orders // typical to any stateless bean
package factory.manage_orders;
import javax.ejb.*;
public interface ManageOrders extends EJBHome{
ManageOrders create()throws java.rmi.RemoteException, java.ejb.CreateException;
}
Implementation of ManageOrdersEJB
package factory.manage_orders;
public class ManageOrdersEJB implements SessionBean{
void placeOrder(int salesDivision, int orderNumber, String productName, Date datedue)
try{//find product
ProductHome phome= get ProductHome();
Product p=phome.findByPrimaryKey(productName);
//create order
OrderHome ohome=getOrderHome();
Ohome.create(int salesDivision, int orderNumber, String productName, Date datedue);
}catch (NamingException ne){throw new EJBException(ne)
}catchFinderException fe){
If (fe instanceOf objectNotFoundException) throw NoSuchProductException(fe)
}catch(CreateException ce){
if (OrderExists(int salesDivision, int orderNumber)){
throw new DuplicateOrderException(ce);
else { throw new EJBException(ce)}
placeOrder() method makes use of both entity beans.
It uses getProductHome() helper method to get a reference to ProductHome
uses it to call getByPrimaryKey().
and getOrderHome() to get reference to OrderHome and
Use the reference to call create() method of entitybean Order
.
Exceptions
If finder exception is result of product not being found in database,
NosuchProduct exception is thown , if it due to indeterminate cause, a general
EJBException is thrown, similary with createException, here it uses helper
function orderExists()
void cancelOrder(int salesDivision, int orderNumber) throws RemoteException,
orderNotCancelableException, NosuchOrderException{
try{
OrderHome oh= getOrderHome();
OrderPk pk= new OrderPk(int salesDivision, int orderNumber);
Order od=oh.findByPrimarykey(pk);
od.cancel();
}catch( Exception e){}
void createSampleProducts()
try{
ProductHome ph=getProductHome();
ProductCreationHelper pch= new ProductCreationHelper(ph);
// helper class
pch.createAll();}catch (Exception e ){}
Helper class
package factory.manage_orders;
imports
public class ProductCreationHelper{
ProductHome productHome;
public ProductCreationHelper(ProductHome ph){this. productHome = productHome;}
public void createALL(){
try{
createDesk();
createChair();
createLamp();
}catch(Exception e) throw new EJBException}
public void createDesk()throws Exception{RoutingInstruction compress = new
RoutingInstruction(5,"Compress the wood.");
RoutingInstruction stain = new RoutingInstruction(10, "Stain the wood.");}
productHome.create("CHAIR01", "Quality Plastic Chair", routings);}}
OpenOrderView[] getSchedulableOrders() throws RemoteException{}
void createProduct(String id, String name) throws RemoteException{}
void addRoutingInstruction(String id, int sequence , String instruction) throws
RemoteException{}
//helper methods
private boolean orderExists(int salesDivision int orderNumber){
try{
OrderHome oh =getOrderHome();
OrderPK pk=new OrderPK(salesDivision, orderNumber);
Order or=oh.findByPrimaryKey(pk);
return true;}
catch (Exception e){ return false}
}
OverdueOrderView[] getOverdueOrders() {
try
{
LinkedList overdueOrders = new LinkedList();
Date today = new Date();
long todayMillis = today.getTime();
long leadTimeMillis = getLeadTimeDays() *MILLIS_IN_DAYS;
OrderHome orderHome = getOrderHome();
Collection uncompletedOrders = orderHome.findUncompletedOrders();
Iterator iterUncompletedOrders = uncompletedOrders.iterator();
while(iterUncompletedOrders.hasNext(){
find all orders which are to be produced or in production
and put them in array of type OverdueOrderView
}catch(exception e){throw EJBException}
Private int getLeadTimeDays() throws NamingException{
Integer leadTimeDays= (Integer).initial.lookup(“java:comp/env/lead_time”);
Return leadTimeDays.intValue();
}
private OrderHome getOrderHome()throws NamingException{
InitialContext I=new InitalContext():
OrderHome home=(orderHome)javax.rmi.
PortableRemoteObject.narrow(initial.lookup(“java:comp/env/ejb/Order”)
Return home;}
//lifecycle methods
public void ejbCreate(){}
public void ejbActivate(){}
public void ejbPassivate(){}
public void ejbRemove(){}
public void setSessionContext(SessionContext ct){}
Helper functions provide functionality to business methods
These methods are private
The method getLeadTime() retrieves Leadtime from beans JNDI environment
This read-only information is specified in deployment descriptor,
To change this information edit deployment descriptor and redeploy the bean,
better than hardcoding in bean, in which case need to rebuild the bean and redeploy.
What type of information
Customization information like company’s name, IPaddress, SQL statement to direct
database access.
Environment entries can be following type String,Boolean,Byte,Short,Integer,
Long,Float,Double.
They can be specified tool provided by application server vendor
Or edited by hand.
The names specified will be available “java:comp/env”
The method getOrderHome retrieves home interface of entity bean “Order”
Bean developer declares logical names of beans that they reference in deployment descriptor
Deployment descriptor
<env-enrty>
<env-entry-name>lead_time</env-entry-name>
<env-entry-type>java.lang.Integer</env-entry-type>
<env-entry-value>4</env-entry-value>
</env-entry>
<ejb-ref>
<ejb-ref-name>ejb/Order</ ejb-ref-name>
<ejb-ref-type>Entity</ ejb-ref-name>
<home>factory.order.OrderHome</home>
<remote>factory.order.Order</remote>
<ejb-link>Orders</ejb-link> // optional
</ejb-ref>
Manufacture stateful session bean remote interface
package factory.manufacture;
import statements...
public interface Manufacture extends EJBObject{
OpenOrderView[] getOpenOrders() throws remoteException;
void selectForManufacture( int salsdiv,int ordno) extends
RemoteException,NosuchOrderException, BadStatusException;
Boolean hasNextRouting()throws RemoteException, NoSuchOrderException;
String getNextRouting()throws RemoteException, NoSuchOrderException;
void ship(String carrier,int loaddock) throws RemoteException, NoSelectionrException;
}
Unlike in manageOrder (stateless bean) there is
an implied order in which the methods should
be called in this interface,
Select a product
Work through routing(building it)
Ship it
failing to do will throw noSuchSelection
exception
Home interface
package factory.manage_orders;
import javax.ejb.*;
public interface ManufactureHome extends EJBHome{
Manufacture create( String manf_cellid)throws java.rmi.RemoteException,
java.ejb.CreateException;
}
Stateful session bean implementation
package factory.manufacture;
import statements
public class ManufactureEJB implements session bean{
// properties
public string manf_cellid;
public List routing instructions;
public int currentposition, last position;
// framework & lifecycle methods
public void ejbcreate(String manf_cellid){
this.manf_ceddid= manf_cellid;
}
public void ejbActivete(){}
public void ejbpassivate(){}
public void ejbRemove(){}
public void setSessionContext(SessionContext ctx){}
//business methods
public OpenOrderView[] getOpenOrders(){
ManageOrdersHome hmo=getManageOrdersHome();
ManageOrders mo= hmo.create();
return mo.getSchedulableOrders();
}catch(Exception e){throw new EJBException e}
Public void selectForManufacture(int SalesDivsion, int orderNumber){
OrderHome ho=getOrderHome();
OrderPK pk=new OrderPK(salesDivision, orderNumber);
Order ord=ho.getByPrimaryKey(pk);
String ordstat=ord.getStatus();
If(ordstat !=StatusString.OPEN)throw BadStatusException ;
ord.beginManufacture()
Product pr=ord.getProductOrdered();
RoutingInstructions[] productRouting=pr.getRoutingInstructions();
RoutingInstruction[] productRouting = product.getRoutingInstructions();
routingInstructions = Arrays.asList(productRouting);
Currentposition=0; Lastposition= routingInstructions.size()-1;
SelectedSalesDivision= SalesDivsion;
SelectedOrderNumber= orderNumber;
orderSelected=true;}catch(Exception e){}
The SelectforManufacture() verifies that
order exists and is eligible for
manufacture
Set the status so other manufacturing
units will realize order is being built.
Retrives routing instruction and put them
in variable as cache
public void ship(String carrier, int dock){
If (!orderSelected)throw new NoSelectionException();
Connection con=null;
try{
con=getConnection();
PreparedStatement st= con.prepareStatement(getShipmentSQLString());
st.setInt(1,selSalesDiv);
statement.setInt(2, selectedOrderNumber);
statement.setString(3, carrier
st.excuteUpdate();
st.close();
con.close();
orderSelected=false;
Find the Order And call order.completeManufacture();
}
Catch(Exception e){throw new EJBException(e)}
Private String getShipmentSQLString()thows exception
InitialContext ic=new InitialContext();
String sql=(String)ic.lookup(“java:/comp/env/ shipmentsSQL”);
Return sql}
<env-enrty>
<env-entry-name> shipmentsSQL </env-entry-name>
<env-entry-type>java.lang.string</env-entry-type>
<env-entry-value>insert into shipments (dividion, oredrnumber, carrier,
loadingdock,datecompleted, manufactured_by) values(?,?,?,?,?,?)</env-entryvalue>
</env-entry>
//helper functions
private Connection getConnection()throws Exception{
Context in=new IntialContext();
DataSource dataSource=(DataSource)initial.lookup(“java:comp/env/jdbc/shipDB”);
Return dataSource.getConnection}
<resouce-ref>
res-ref-name>jdbc/shipDB</res-ref-name>
res-type>javax.sql.DATASource</res-type>
res-auth>Container</res-auth>
</resource-ref>
Questions ?