Sample Program -Restaurant

Sample Program Restaurant

In the following sections you will be building a sample program that simulates a subset of the workings of a restaurant. In the restaurant Taste of Sams, you have waiters and chefs to provide service to customers. Customers are directly served by a waiter in the restaurant. One waiter serves one customer. A waiter takes the customer's order of menu items and forwards the order to any of the chefs in the restaurant to process the order. The chef who is processing the order returns the cooked items to the waiter, who in turn presents it to the customer. At the end of the meal, the waiter presents the check to the customer. Finally, the customer makes the payment to the waiter. All these activities constitute the requirements for building the restaurant application.

This entire work flow can be mapped into the EJB architecture components. Now you'll design the above requirements to build the restaurant application. The first step in the design process is to identify the primary actors in the application. At first glance, the actors can be easily listed:

  • Customer

  • Waiter

  • Chef

From the activities of these actors described in the requirements, you can map these to EJBs for your application. From the previous sections, you have an understanding of the features of stateful and stateless session beans. Because the waiter services one customer at a time till the customer exits from the restaurant, you can easily model the activities of the waiter as a stateful session bean. The customer in the restaurant is the EJB client. The chefs in the restaurant are not tied to any customer or waiter in the restaurant. Hence, the chefs in the restaurant can be modeled as stateless session beans.

Now that you have mapped the actors in the restaurant sample application to EJBs, look at the detailed design of the different classes and interfaces that will be required for the restaurant sample application. You will group these classes in the com.sams.learnweblogic7.ejb.stateful package. From Figure 10.10 you can design classes and interfaces in the following section.

Figure 10.10. Class diagram of the classes and interfaces for the restaurant application.

graphics/10fig10.gif

Waiter Classes and Interfaces

The waiter will be modeled as a stateful session bean. Hence, you will create the following classes and interfaces:

  • WaiterInterface The remote interface of the Waiter stateful session bean. The services offered by the waiter to the customer are defined as methods in the WaiterInterface remote interface.

  • WaiterHome The home interface for creating Waiter stateful session beans. The Customer EJB client will use the methods in the WaiterHome interface to obtain instances of the Waiter session bean. The WaiterHome interface will contain create() methods that will be used by the Customer EJB client. The WaiterHome bean will be registered in the naming service of WebLogic Server. The Customer EJB client will retrieve the reference to the WaiterHome from the naming service using the JNDI API.

  • WaiterBean The actual stateful session bean class. The EJB callback methods, such as ejbCreate(), ejbPostCreate(), and so on, will be implemented in the WaiterBean class. Apart from this, the service methods of the waiter that have been defined in the WaiterInterface will be implemented in this class.

Chef Classes and Interfaces

The chefs in the restaurant do not need to maintain any state with either the customer or the waiter. Hence, the chefs can be modeled as stateless session beans. You will be looking at stateless session beans in detail in the next day. Hence, you will build the chef as a stateless session bean in the sample application in the next day. For today, you will build the Chef class as a simple Java class. The chef interface and class are as follows:

  • ChefInterface The interface of the Chef class. The ChefInterface is not a remote interface. The services offered by the Chef class to the WaiterBean will be listed in this interface. You are modeling the ChefInterface to maintain consistency and make it easy to build the chef as a stateless session bean. This will entail minimal changes to the classes and interfaces of the Chef and calling Waiter classes.

  • ChefImpl Because you will not be implementing the Chef class as a stateful session bean for today's sample application, the ChefImpl class is a simple Java class that implements the business methods in the ChefInterface.

The Customer Class

The Customer class represents the customer in the restaurant. The Customer class is the EJB client and interacts with the Waiter stateful session bean. Until the Customer completes its interactions with the waiter, the Waiter stateful session bean maintains state with an instance of the Customer class.

Additional Classes

In addition to the classes already described, you will be using some additional classes to support the various activities in the application. These are as follows:

  • Restaurant Used as a façade class for all the classes related to the restaurant. A Customer class will initiate interaction with a Restaurant class.

  • MenuList Used to store the list of menu items that will be presented by the waiter to the customer.

  • MenuItem Identifies the contents of a single menu item. A collection of MenuItem objects will be stored in the MenuList.

  • Order Encapsulates the customer's order.

  • PoolClass Used by the Waiter class to obtain a chef to process the customer's order. This class will be removed once you model the Chef class as a stateless session bean. The EJB container will maintain the pool of Chef bean instances in that case.

  • CookedItemInterface Defines the services for cooking a menu item. The CookedItemInterface is implemented by the CookedItemImpl class.

  • CookedItemImpl Implements the functionality defined in the CookedItemInterface. The Chef class uses this class for processing the customer's order sent by the waiter.

Naming Conventions

Because there are many classes and interfaces involved while building an EJB, it is always a good practice to follow naming conventions for the different classes and interfaces. This will help you in the future when maintaining an application containing many EJBs. The naming conventions used in this book for EJBs are as follows:

For the local or remote interfaces, use the suffix Interface after the application-specific name, for example, WaiterInterface.

For the home interfaces, use the suffix Home after the application-specific name, for example, WaiterHome.

For the actual bean implementation class, use the suffix Bean after the application-specific name, for example, WaiterBean.

The EJBs are also grouped together into Java packages based on their types session, entity, or message. Within a session bean you are going down one level further to identify whether the bean is stateful or stateless, for example, package com.sams.learnweblogic7.ejb.stateful.

Source Code

Now look at the source code for these classes and interfaces. Because there are many classes and interfaces involved when building a stateful session bean, you will study these step by step. First look at the source code for the classes and interfaces of the waiter in Listing 10.1.

Listing 10.1 WaiterInterface.java
 package com.sams.learnweblogic7.ejb.stateful; import java.rmi.RemoteException; import javax.ejb.EJBObject; import java.util.*; /** * This is the waiter interface, looked up by the restaurant * and passed to the client. * This interface, which extends EJBObject, is the remote interface. * The business methods are defined here. */ public interface WaiterInterface extends EJBObject {        public MenuList getMenu() throws RemoteException;        public void getOrder(MenuItem orderedItem, int quantity) throws                RemoteException;        public void confirmOrder() throws RemoteException;        public ChefInterface getChefFromChefPool() throws RemoteException;        public Vector serveCookedItem() throws RemoteException;        public float getCheck() throws RemoteException; } 

As discussed earlier, the services offered by the Waiter stateful session bean are declared in the WaiterInterface shown in Listing 10.1. Depending on the implementation, this interface can be either remote or local. For remote interfaces, the WaiterInterface extends EJBObject; for local interfaces, the WaiterInterface extends EJBLocalObject. The different services provided by the waiter are encapsulated in these methods: getMenu(), getOrder(), confirmOrder(), getChefFromChefPool(), serveCookedItem(), and getCheck(). All of these methods will throw the java.rmi.RemoteException because you are designing the waiter EJB to be accessed remotely. If you design your EJB to be accessed locally, the methods in the interface will throw the javax.ejb.EJBException.

The WaiterHome interface in Listing 10.2 enables the Customer class (EJB client) to obtain a handle to the WaiterBean stateful session bean. The create() method defined in the WaiterHome interface returns an object of type WaiterInterface, which is the remote (or local) object reference. The WaiterHome interface extends the javax.ejb.EJBHome interface. The create() method throws the javax.ejb.CreateException and java.rmi.RemoteException (for remote interfaces only) exceptions when an error occurs while creating the WaiterInterface remote object. You can write overloaded create() methods by passing, say, the customer's name as a parameter. So for the life of the WaiterBean stateful session bean, the waiter will be identified with that customer.

Listing 10.2 WaiterHome.java
 package com.sams.learnweblogic7.ejb.stateful; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; /**  * This is the home interface for the ChefBean.java.  * In WebLogic, this is implemented by the code-generated container  * class ChefBeanC. A home interface may support one or more create  * methods, which must correspond to methods named "ejbCreate" in the EJBean.  *  */ public interface WaiterHome extends EJBHome {   /**    * Corresponding to the ejbCreate method in the WaiterBean.java.    *    * @return                  WaiterInterface    * @exception               RemoteException    * @exception               CreateException    */   WaiterInterface create() throws CreateException, RemoteException; } 

The final class that you will be studying for the Waiter stateful session bean is the WaiterBean class; see Listing 10.3.

Listing 10.3 WaiterBean.java
 package com.sams.learnweblogic7.ejb.stateful; import java.util.*; import java.rmi.RemoteException; import java.util.Properties; import javax.ejb.CreateException; import javax.ejb.RemoveException; import javax.naming.*; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import javax.ejb.*; public class WaiterBean implements SessionBean {        //defining private and public variables, for the list of items                ordered by client, and items cooked by chef.        private Vector orderedItemsList = new Vector();        private Vector cookedItems = new Vector();        public String tempString = "Trial String";        private static final boolean ENABLE_WEBLOGIC_LOGGING = true;     private SessionContext ctx;        // Using WebLogic's log service to log events        private void webLogicLog(String logMessage) {               if (ENABLE_WEBLOGIC_LOGGING)                      System.out.println(logMessage);        } //end of webLogicLog        /**         * As per EJB Specification's to be implemented by bean,         * Used when create is called on the remote interface         */        public void ejbCreate(){               webLogicLog("Method ejbCreate has been called");        }        /**         * As per EJB Specification's to be implemented by bean,         * Presently not being used         */        public void ejbActivate() {               webLogicLog("Method ejbActivate has been called");        }//end of ejbActivate        /**         * As per EJB Specification's to be implemented by bean,         * Presently not being used         */        public void ejbRemove() {               webLogicLog("Method ejbRemove has been called");        }//end of ejbRemove        /**         * As per EJB Specification's to be implemented by bean,         * Presently not being used         */        public void ejbPassivate() {               webLogicLog("Method ejbPassivate has been called");        }//end of ejbPassivate        /**         * Sets the session context.         *         * @param ctx SessionContext Context for session         */        public void setSessionContext(SessionContext ctx) {               webLogicLog("Method setSessionContext has been called");               this.ctx = ctx;        }//end of setSessionContext        //method called by client to get a list of Menu items.        public MenuList getMenu(){               return MenuList.getMenu();        }        //method called by client to get the order.        //The client gets the menu item id from the menu list,        //and also specifies the number of items.        public void getOrder(MenuItem orderedItem, int quantity){               System.out.println("Item ordered : "+orderedItem.getItemDesc());               System.out.println("Item qty ordered : "+quantity);               orderedItemsList.addElement(new Order(orderedItem, quantity));        }        //the client calls this method to confirm his order.        //When he does this, the waiter requests a chef from the chef pool        // and sends the item to be prepared to the chef.        //The chef returns the cooked item. The waiter then collects        //all the cooked items into his tray (the global vector),        //returns the cook into the cook pool.        public void confirmOrder(){               CookedItemImpl currentCookedItem;               MenuItem menuItemToBeProcessed;               Enumeration orderedItemsEnum = orderedItemsList.elements();               while(orderedItemsEnum.hasMoreElements())               {                      try{                             ChefInterface currentChef = getChefFromChefPool();                             System.out.println("Chef Interface returned to                                     confirm Order is "+currentChef);                             menuItemToBeProcessed =                                     ((Order)orderedItemsEnum.nextElement()                                     ).getItem();                             System.out.println("menuItem to be processed                                     in confirm order, before calling cookitem "+                                     menuItemToBeProcessed.getItemDesc());                             currentCookedItem =                                     currentChef.cookItem(menuItemToBeProcessed);                             System.out.println(                                     "Current cooked item before adding to vector                                     is"+currentCookedItem.getIngredients());                             cookedItems.addElement(currentCookedItem);                      }                      catch(Exception e){                             e.printStackTrace();                      }               }        }        //called by the waiter to get a chef from the chef pool        public ChefInterface getChefFromChefPool(){               return PoolClass.getChef();        }        //performed by the waiter after all the items are cooked,                and collected in the vector, and then serves the client.        public Vector serveCookedItem(){               return cookedItems;        }        //called by the client, to get his check.        public float getCheck(){               float checkSum = 0;               Enumeration orderedItemsEnum = orderedItemsList.elements();               while(orderedItemsEnum.hasMoreElements())               {                      Order individualCurrOrder =                              (Order)orderedItemsEnum.nextElement();                      checkSum +=                              (individualCurrOrder.getItem()).getItemPrice()                              *individualCurrOrder.getQty();               }               return checkSum;        } } 

The WaiterBean class is the heart of the stateful session bean and contains all the functionality associated with the waiter. Because the WaiterBean is a session bean, it implements the javax.ejb.SessionBean as a part of its adherence to the Component Contract EJB design contract. The life-cycle callback methods of a session bean, such as setSessionContext(), ejbCreate(), ejbRemove(), ejbActivate(), and ejbPassivate() are implemented by this class. The EJB container will invoke these methods at different stages in the WaiterBean bean's life cycle. Apart from these methods, the WaiterBean provides the functionality for the service methods defined in the WaiterInterface interface. The methods getMenu(), getOrder(), confirmOrder(), and getCheck() are invoked by the Customer EJB client. Take a quick look at the confirmOrder() method, which is where the major part of the action takes place:

 public void confirmOrder(){         CookedItemImpl currentCookedItem;        MenuItem menuItemToBeProcessed;        Enumeration orderedItemsEnum = orderedItemsList.elements();        while(orderedItemsEnum.hasMoreElements())        {               try{                      ChefInterface currentChef = getChefFromChefPool();                      System.out.println(                              "Chef Interface returned to confirm Order is                              "+currentChef);                      menuItemToBeProcessed =                              ((Order)orderedItemsEnum.nextElement()).getItem();                      System.out.println(                              "menuItem to be processed in confirm order,                              before calling cookitem                              "+menuItemToBeProcessed.getItemDesc());                      currentCookedItem =                              currentChef.cookItem(menuItemToBeProcessed);                      System.out.println(                              "Current cooked item before adding to vector                              is"+currentCookedItem.getIngredients());                      cookedItems.addElement(currentCookedItem);               }               catch(Exception e){                      e.printStackTrace();               }        } } 

The WaiterBean bean in turn interacts with the Chef class after obtaining a reference to a ChefInterface object from the PoolClass in the getChefFromPool() method. In tomorrow's example, you will implement the chef as a stateless session bean. From the code snippet above, after obtaining a reference to the ChefInterface object, the WaiterBean invokes the cookItem() method on the ChefInterface object and passes it the menu item to be cooked. If there are multiple items ordered by the Customer class, the WaiterBean contacts another ChefInterface object (retrieved from the PoolClass) and passes it the next menu item. This is done because one chef is dedicated to cooking one menu item at a time. The cookItem() method of the ChefInterface returns a CookedItemImpl object, which represents the finished product. The multiple cooked items are added to a vector and stored by the WaiterBean bean. After placing the order using the confirmOrder() method of the WaiterBean, the Customer EJB client invokes the serveCookedItems() method. The WaiterBean returns the vector of CookedItemImpl objects to the Customer class. Finally, the Customer class invokes the getCheck() method on the WaiterBean class:

 //called by the client, to get his check.  public float getCheck(){        float checkSum = 0;        Enumeration orderedItemsEnum = orderedItemsList.elements();        while(orderedItemsEnum.hasMoreElements())        {               Order individualCurrOrder =                       (Order)orderedItemsEnum.nextElement();               checkSum +=                        (individualCurrOrder.getItem()).getItemPrice()                        *individualCurrOrder.getQty();        }        return checkSum; } 

The preceding code snippet shows the getCheck() method. The entire list of ordered items is traversed, and the cost of each menu item is calculated, taking into consideration the quantity of menu items ordered. The final check is presented to the Customer class by the WaiterBean.

Up till this point you have seen the source code for the stateful session EJB. Now take a look at how an EJB client uses the services provided by the stateful session bean. The source code for the Customer class, which is the EJB client, is given in Listing 10.4.

Listing 10.4 Customer.java
 import com.sams.learnweblogic7.ejb.stateful.*; import java.rmi.RemoteException; import java.util.Properties; import javax.naming.*; import java.util.*; import java.io.*; import java.text.*; import javax.rmi.PortableRemoteObject; public class Customer{        private static final String WAITERHOME_JNDI_NAME = "Waiter_Home";        private static final String DESIGN_DASH =               "-------------------------------------------------------------------";        /**         * This is a standalone client.    * We run this example from the command line.    */   public static void main(String[] args) {         /**         * create a context object. First create env Hashtable         * and pass the hashtable as a parameter to the constructor.         **/          Context ctx = null;       try {         Hashtable env = new Hashtable();         env.put(           Context.INITIAL_CONTEXT_FACTORY,           "weblogic.jndi.WLInitialContextFactory"         );         ctx = new InitialContext(env);         System.out.println("Initial context created");                             Hashtable restaurantEnv = new Hashtable();                             restaurantEnv.put(Context.INITIAL_CONTEXT_FACTORY,                                     "com.sun.jndi.fscontext.                                     RefFSContextFactory");                             restaurantEnv.put(Context.PROVIDER_URL,                                     "file:/c:/book");                             Context initCtx = new InitialContext(restaurantEnv);                             System.out.println("Created new initial context");                             try{                                    File restPropsFile =                                            (File)initCtx.lookup("code" +                                            File.separator + "Jndi" +                                            File.separator + "Client" +                                            File.separator + "RestaurantProps.prop");                                    FileInputStream restPropsFileInputStream =                                            new FileInputStream(restPropsFile);                                    Properties restaurantProps =                                            new Properties();                                    restaurantProps.load(                                            restPropsFileInputStream);                                    //decided to go to the restaurant                                     //"The taste of Sams"                                    String restaurantCity =                                            restaurantProps.getProperty                                            ("The_Taste_Of_Sams_City");                                    System.out.println(restaurantCity);                                    String restaurantState =                                            restaurantProps.getProperty                                            ("The_Taste_Of_Sams_State");                                    System.out.println(restaurantState);                                    String restaurantType =                                            restaurantProps.getProperty                                            ("The_Taste_Of_Sams_Type");                                    System.out.println(restaurantType);                             }                             catch(Exception e){                                    e.printStackTrace();                             }                             /**                                  * Since the client enters the restaurant,                                  * to enter, create a restaurant object.                                  * then enter the restaurant by calling the                                  * enterRestaurant method. Perform a                                  * context lookup for the Waiter Object.                                  * then perform a lookup for the waiter object.                             **/                                    try {                                    Restaurant samsRestaurant = new Restaurant();                                    String welcomeString =                                            samsRestaurant.enterRestaurant();                                    System.out.println(DESIGN_DASH);                                    System.out.println(welcomeString);                                    //lookup for waiter ejb object                                    WaiterInterface thisWaiterObj = null;                                    try{                                           WaiterHome waiterHome = lookUpHome();                                           thisWaiterObj =                                                    (WaiterInterface)                                                    PortableRemoteObject.narrow(                                                    waiterHome.create(),                                                    WaiterInterface.class);                                    }                                    catch(Exception e){                                           e.printStackTrace();                                    }                                    //once the waiter object is obtained,                                    //request the waiter to get the menu list.                                    MenuList myMenuList =                                            thisWaiterObj.getMenu();                                    System.out.println(DESIGN_DASH);                                    System.out.println("Menulist returned");                                    //ordering items 1, 2 and 3. To do that,                                    //pick up the items from the menulist first.                                    MenuItem orderedItem1 =                                            (MenuItem)myMenuList.get("1");                                    MenuItem orderedItem2 =                                            (MenuItem)myMenuList.get("2");                                    MenuItem orderedItem3 =                                            (MenuItem)myMenuList.get("3");                                    thisWaiterObj.getOrder(orderedItem1, 1);                                    thisWaiterObj.getOrder(orderedItem2, 2);                                    thisWaiterObj.getOrder(orderedItem3, 3);                                    //confirming the order                                    thisWaiterObj.confirmOrder();                                    //once the waiter has confirmed the order,                                    //the waiter serves the items.                                    Vector cookedItems =                                            thisWaiterObj.serveCookedItem();                                    System.out.println(DESIGN_DASH);                                    System.out.println("The served items are:");                                    Enumeration servedItemsEnum =                                            cookedItems.elements();                                    while(servedItemsEnum.hasMoreElements()){                                           CookedItemImpl servedItem =                                                   (CookedItemImpl)                                                   servedItemsEnum.nextElement();                                           System.out.println(DESIGN_DASH);                                           System.out.println(                                                   "Item Name                                                   :"+servedItem.getItemName());                                           System.out.println(                                                   "Serving Size                                                   :"+servedItem.getServingSize()                                                   );                                           System.out.println(                                                   "Taste of Item                                                   :"+servedItem.getTaste());                                           System.out.println(                                                   "Ingredients of Item                                                   :"+servedItem.getIngredients()                                                   );                                           System.out.println(                                                   "Temperature of Item                                                   :"+servedItem.getTemperature()                                                   );                                    }                                    //After serving, client requests check                                    float bill = thisWaiterObj.getCheck();                                    System.out.println("Your bill is $"+bill);                                    }                                    catch (Exception e) {                                           System.out.println(e.toString());                                    }            }               catch (Exception e) {               System.out.println(e.toString());               }               finally {                      if (ctx != null) {                             try {                                    ctx.close();                             }                             catch (NamingException e) {                                    System.out.println(                                            "Failed to close context due to: " + e);                             }                      }               }        }//end of main        /**        * Lookup the EJBs home in the JNDI tree        */        public static WaiterHome lookUpHome() throws NamingException        {        // Loo kup the waiter home bean home using weblogic JNDI        //(Properties can be used instead of Hashtable,        //to maintain jdk1.1 compatibility)         try{               Hashtable h = new Hashtable();               h.put(Context.INITIAL_CONTEXT_FACTORY,                       "weblogic.jndi.WLInitialContextFactory");               h.put(Context.PROVIDER_URL, "t3://localhost:7001");               Context ctx = new InitialContext(h);               System.out.println(                       "Initial context to look up chef home created"+ctx);               String ctxName = ctx.getNameInNamespace();               NamingEnumeration myNamingEnum = ctx.list(ctxName);               while(myNamingEnum.hasMoreElements()){                      System.out.println("Naming Enum : "+myNamingEnum.nextElement());               }               Object home = ctx.lookup(WAITERHOME_JNDI_NAME);               System.out.println("Lookup performed");               return (WaiterHome)PortableRemoteObject.narrow(                       home, WaiterHome.class);         }         catch (NamingException namingException) {               System.out.println("Unable to lookup EJBHome WaiterHome.");               System.out.println(                       "Check JNDI name "+WAITERHOME_JNDI_NAME+" on the WebLogic                       server");               throw namingException;         }        } }//end of Customer 

The Customer class is the EJB client for the WaiterBean stateful session bean. This is a standalone Java application with all the functionality in the main() method. The first step that the Customer class does is to get a reference to WebLogic's naming service using the JNDI API. This is exactly similar to the JNDI client that you built in yesterday for learning the JNDI API. Your restaurant application actually begins when the customer enters the restaurant:

  ...  try {         Restaurant samsRestaurant = new Restaurant();         String welcomeString =                 samsRestaurant.enterRestaurant();         System.out.println(DESIGN_DASH);         System.out.println(welcomeString);         //lookup for waiter ejb object         WaiterInterface thisWaiterObj = null;         try{                WaiterHome waiterHome = lookUpHome();                thisWaiterObj =                        (WaiterInterface)                        PortableRemoteObject.narrow(                        waiterHome.create(),                        WaiterInterface.class);         }         catch(Exception e){               e.printStackTrace();         }                             ... 

The Customer class creates a new Restaurant object and calls the enterRestaurant() method. The enterRestaurant() method returns a welcome message to the Customer class. After this, the Customer class needs to interact with the waiter to access its services. For this, the Customer class looks up the naming service to obtain a reference to the WaiterHome object using the JNDI API. This is done in the lookupHome() method in the following code snippet:

 /**  * Lookup the EJBs home in the JNDI tree */ public static WaiterHome lookUpHome() throws NamingException { // Look up the waiter home bean home using weblogic JNDI //(Properties can be used instead of Hashtables // to keep the code compatible with jdk1.1 also.)  try{        Hashtable h = new Hashtable();        h.put(Context.INITIAL_CONTEXT_FACTORY,                "weblogic.jndi.WLInitialContextFactory");        h.put(Context.PROVIDER_URL, "t3://localhost:7001");        Context ctx = new InitialContext(h);        System.out.println("Initial context to look up chef home created"                +ctx);        String ctxName = ctx.getNameInNamespace();        NamingEnumeration myNamingEnum = ctx.list(ctxName);        while(myNamingEnum.hasMoreElements()){                System.out.println("Naming Enum : "+myNamingEnum.nextElement());        }        Object home = ctx.lookup(WAITERHOME_JNDI_NAME);        System.out.println("Lookup performed");        return (WaiterHome)PortableRemoteObject.narrow(                home, WaiterHome.class);         }  catch (NamingException namingException) {        System.out.println("Unable to lookup EJBHome WaiterHome.");        System.out.println("Check JNDI name "+WAITERHOME_JNDI_NAME+"                on the WebLogic server");        throw namingException;  } } 

The call to the lookup() method of the InitialContext object is passed the JNDI name of the WaiterHome object. The lookup() method returns the reference to the WaiterHome object stored in the naming service. The WaiterHome object is registered in WebLogic's naming service during deployment. You will learn how to deploy the WaiterHome in the section "Deploying the Program."

After obtaining the reference to the WaiterHome object, the Customer class uses the WaiterHome object to create a stateful session bean of type WaiterInterface. This is done as follows:

 //lookup for waiter ejb object  WaiterInterface thisWaiterObj = null; try{        WaiterHome waiterHome = lookUpHome();        thisWaiterObj =                (WaiterInterface)PortableRemoteObject.narrow(                waiterHome.create(),WaiterInterface.class); } catch(Exception e){        e.printStackTrace(); } 

The create() method of the WaiterHome object is invoked by the Customer class. The create() method returns a reference to the stateful session bean of type WaiterInterface. Now the Customer class is set to interact with the WaiterBean using the WaiterInterface object:

 //once the waiter object is obtained,  //request the waiter to get the menu list MenuList myMenuList = thisWaiterObj.getMenu(); System.out.println(DESIGN_DASH); System.out.println("Menulist returned"); //ordering items 1, 2 and 3. To do that, //picking up the items from the menulist first. MenuItem orderedItem1 =         (MenuItem)myMenuList.get("1"); MenuItem orderedItem2 =         (MenuItem)myMenuList.get("2"); MenuItem orderedItem3 =         (MenuItem)myMenuList.get("3"); thisWaiterObj.getOrder(orderedItem1, 1); thisWaiterObj.getOrder(orderedItem2, 2); thisWaiterObj.getOrder(orderedItem3, 3); //confirming the order thisWaiterObj.confirmOrder(); 

This code snippet shows the Customer obtaining the menu from the WaiterBean using the getMenu() method of the WaiterInterface object.

After this the Customer class selects menu items and places the order with the waiter using the confirmOrder() method:

 //once the waiter has confirmed the order,  //the waiter serves the items. Vector cookedItems =         thisWaiterObj.serveCookedItem(); System.out.println(DESIGN_DASH); System.out.println("The served items are:"); Enumeration servedItemsEnum =         cookedItems.elements(); while(servedItemsEnum.hasMoreElements()){        CookedItemImpl servedItem =                (CookedItemImpl)servedItemsEnum.nextElement();        System.out.println(DESIGN_DASH);        System.out.println(                "Item Name :"+servedItem.getItemName());        System.out.println(                "Serving Size :"+servedItem.getServingSize());        System.out.println(                "Taste of Item :"+servedItem.getTaste());        System.out.println(                "Ingredients of Item :"+servedItem.getIngredients());        System.out.println(                "Temperature of Item :"+servedItem.getTemperature());        } 

Once the order is confirmed, the WaiterBean serves the cooked items to the customer. You will print the cooked items on the screen to verify the list of cooked items received. Here you can see that the behind-the-scenes functionality of the WaiterBean bean which interacts with the ChefImpl class, forwards the customer's order to it, and receives the cooked items is totally hidden from the customer. For the Customer class, the WaiterBean is the single point of contact to place orders and receive the cooked items. Also, because the WaiterBean is stateful, there can be a time lag between the confirmOrder() and serveCookedItems() calls to the WaiterBean bean. The Customer class will have the same WaiterBean bean reference with which it was interacting till that point. This, in essence, is how a stateful session bean functions.

Finally, the Customer class calls for the check using the getCheck() method of the WaiterBean bean:

 //After serving, client requests check  float bill = thisWaiterObj.getCheck(); System.out.println("Your bill is $"+bill); } catch (Exception e) {        System.out.println(e.toString()); } 

You have looked at the main classes and interfaces that compose the stateful session bean and the EJB client. Listings 10.5 through 10.12 show the other classes that are a part of the application but do not have any EJB functionality.

Listing 10.5 Restaurant.java
 package com.sams.learnweblogic7.ejb.stateful; import javax.naming.*; import java.util.*; import java.io.*; import java.text.*; public class Restaurant {        public String enterRestaurant(){               return "Welcome To The Taste of Sams";        } } 
Listing 10.6 MenuItem.java
 package com.sams.learnweblogic7.ejb.stateful; import java.io.Serializable; public class MenuItem implements Serializable {        private String itemDesc;        private float itemPrice;        public MenuItem(String itemDesc, float itemPrice){               this.itemDesc = itemDesc;               this.itemPrice = itemPrice;        }        public String getItemDesc(){               return this.itemDesc;        }        public float getItemPrice(){               return this.itemPrice;        } } 
Listing 10.7 MenuList.java
 package com.sams.learnweblogic7.ejb.stateful; import java.util.*; import java.io.*; public class MenuList extends Hashtable implements Serializable {        private static MenuList objMenuList;        private MenuList(){        }        static{               objMenuList = new MenuList();               objMenuList.put("1",new MenuItem("Apple Pie",5));               objMenuList.put("2",new MenuItem("Banana Split Icecream",5));               objMenuList.put("3",new MenuItem("Cheese Pizza",5));               objMenuList.put("4",new MenuItem("Curly Fries",5));               objMenuList.put("5",new MenuItem("Delhi Kababs",5));               objMenuList.put("6",new MenuItem("Fresh Pineapple Cake",5));               objMenuList.put("7",new MenuItem("French Fries - Tub",5));               objMenuList.put("8",new MenuItem("Hot Dog",5));               objMenuList.put("9",new MenuItem("Hamburger",5));        }        public static MenuList getMenu(){               return objMenuList;        } } 
Listing 10.8 Order.java
 package com.sams.learnweblogic7.ejb.stateful; public class Order implements java.io.Serializable {        private MenuItem item;        private int qty;        public Order(MenuItem orderedItem, int quantity){               this.item = orderedItem;               this.qty = quantity;        }        public MenuItem getItem(){               return this.item;        }        public int getQty(){               return this.qty;        } } 
Listing 10.9 ChefInterface.java
 package com.sams.learnweblogic7.ejb.stateful; public interface ChefInterface {        public CookedItemImpl cookItem(MenuItem orderedItem); } 
Listing 10.10 ChefImpl.java
 package com.sams.learnweblogic7.ejb.stateful; public class ChefImpl implements ChefInterface {        private String chefId;        private boolean isAvailable;        public ChefImpl(String assignChefId){               this.chefId = assignChefId;        }        public String getChefId(){               return chefId;        }        public CookedItemImpl cookItem(MenuItem orderedItem){               CookedItemImpl preparedItem = new CookedItemImpl();               if((orderedItem.getItemDesc()).equals("Apple Pie")){                      preparedItem.setServingSize("Standard");                      preparedItem.setTaste("Sweet");                      preparedItem.setIngredients("Apple, Sugar,                              All Purpose Flour, Eggs, Butter");                      preparedItem.setTemperature("Hot");               }               else if((orderedItem.getItemDesc()).equals("                       Banana Split Icecream")){                      preparedItem.setServingSize("One Scoop");                      preparedItem.setTaste("Sweet");                      preparedItem.setIngredients("Milk, Sugar,                              All Purpose Flour, Eggs, Cream, Bananas");                      preparedItem.setTemperature("Cold");               }               else if((orderedItem.getItemDesc()).equals("Cheese Pizza")){                      preparedItem.setServingSize("Standard");                      preparedItem.setTaste("Salty");                      preparedItem.setIngredients("All Purpose Flour, Cheese,                              Jalapenos, Tomatoes, Bell Peppers, Olives, Salt");                      preparedItem.setTemperature("Hot");               }               else if((orderedItem.getItemDesc()).equals("Curly Fries")){                      preparedItem.setServingSize("Standard");                      preparedItem.setTaste("Salty");                      preparedItem.setIngredients("Low Cholesterol Oil,                              Potatoes cut, Salt");                      preparedItem.setTemperature("Hot");               }               else if((orderedItem.getItemDesc()).equals("Delhi Kababs")){                      preparedItem.setServingSize("10 pieces");                      preparedItem.setTaste("Spicy");                      preparedItem.setIngredients("Onions,Coriander powder,                              Poppy Seeds, Ginger, Salad Oil, Salt, Garlic, Spices,                              Red Chillies, Chicken, Yogurt");                      preparedItem.setTemperature("Hot");               }               else if((orderedItem.getItemDesc()).equals("                       Fresh Pineapple Cake")){                      preparedItem.setServingSize("1 Slice");                      preparedItem.setTaste("Sweet");                      preparedItem.setIngredients("Pineapple, Sugar,                              All Purpose Flour, Eggs, Butter");                      preparedItem.setTemperature("Room Temperature");               }               else if((orderedItem.getItemDesc()).equals("French Fries - Tub")){                      preparedItem.setServingSize("Large");                      preparedItem.setTaste("Salty");                      preparedItem.setIngredients("Low Cholesterol Oil,                              Potatoes cut, Salt");                      preparedItem.setTemperature("Hot");               }               else if((orderedItem.getItemDesc()).equals("Hot Dog")){                      preparedItem.setServingSize("Standard");                      preparedItem.setTaste("Salt");                      preparedItem.setIngredients("Hot Dog Buns, Meat,                              Bread Crumbs, Oatmeal flour, Little Egg White,                              Spices - Onion, garlic, salt, pepper etc");                      preparedItem.setTemperature("Hot");               }               else if((orderedItem.getItemDesc()).equals("Hamburger")){                      preparedItem.setServingSize("Standard");                      preparedItem.setTaste("Salty");                      preparedItem.setIngredients("Hamburger, Lettuce, Onions,                              Tabasco sauce, Cheddar cheese, Kaiser style buns,                              Pam Cooking Spray, Worcestershire sauce");                      preparedItem.setTemperature("Hot");               }               return preparedItem;        } } 
Listing 10.11 CookedItemInterface.java
 package com.sams.learnweblogic7.ejb.stateful; public interface CookedItemInterface extends java.io.Serializable {        public String getServingSize();        public void setServingSize(String servingSize);        public String getTaste();        public void setTaste(String taste);        public String getIngredients();        public void setIngredients(String ingredients);        public String getTemperature();        public void setTemperature(String temperature); } 
Listing 10.12 CookedItemImpl.java
 package com.sams.learnweblogic7.ejb.stateful; public class CookedItemImpl implements CookedItemInterface,         java.io.Serializable{        private String servingSize;        private String taste;        private String ingredients;        private String temperature;        private String itemName;        public String getItemName(){               return this.itemName;        }        public void setItemName(String itemName){               this.itemName = itemName;        }        public String getServingSize(){               return this.servingSize;        }        public void setServingSize(String servingSize){               this.servingSize = servingSize;        }        public String getTaste(){               return this.taste;        }        public void setTaste(String taste){               this.taste = taste;        }        public String getIngredients(){               return this.ingredients;        }        public void setIngredients(String ingredients){               this.ingredients = ingredients;        }        public String getTemperature(){               return this.temperature;        }        public void setTemperature(String temperature){               this.temperature = temperature;        } } 

Well, now that you have written all the classes (quite a few!) for the Restaurant application, take a look at the next step: compiling the program.

Compiling the Program

Compiling the files of the restaurant application is a two-step process. Use the provided compile.bat batch file to compile the classes and interfaces of the restaurant application. This includes the WaiterBean stateful session bean classes, the Customer EJB client, and the supporting Java classes. The batch file compiles the files of the restaurant application located in the directory

 C:\book\code\EJB\stateful\src\*.java  

as can be seen in Figure 10.11.

Figure 10.11. Screen shot showing the directory structure of the source code of the WaiterBean.

graphics/10fig11.jpg

The command used for compiling is

 javac -d C:\book\code\EJB\stateful\deploy C:\book\code\EJB\stateful\src\*.java  

After generating the .class files for the source code, the next step is to edit the deployment descriptor files ejb-jar.xml and the WebLogic specific deployment descriptor file weblogic-ejb-jar.xml to register the stateful session bean with the WebLogic Server.

Figure 10.12 shows the different tags used to register the WaiterBean stateful session bean. Also, the following list will give you a quick look at some of these tags:

  • <ejb-jar></ejb-jar> Encapsulates all the tags used to register the stateful session bean.

  • <enterprise-beans></enterprise-beans> Declares one or many EJBs in the deployment descriptor file.

  • <session></session> Registers information about session beans. Within these tags, you should use the following tags:

    • <ejb-name></ejb-name> The complete name of the EJB should be registered here.

    • <home></home> The complete name (including the package name) of the home interface of the session bean should be defined here. Use the <local-home></local-home> tags for local beans.

    • <remote></remote> The complete name (including the package name) of the remote interface of the session bean should be defined here. If the bean is a local one, use the <local></local> tags.

    • <ejb-class></ejb-class> The complete name (including the package name) of the session bean implementation class should be defined here.

    • <session-type></session-type> Here you should define the type of the session bean, whether stateful or stateless.

    • <transaction-type></transaction-type> These tags are used to define who is responsible when the bean participates in a transaction. The valid values for this are Bean and Container.

  • <assembly-descriptor></assembly-descriptor> Defines information required for deploying, such as security roles, method permissions, transaction attributes, and so on. The following tag is used within the <assembly-descriptor> </assembly-descriptor> tags:

    • <container-transaction></container-transaction> Defines how the container handles the methods of the bean during a transaction. The valid values for this are Bean and Container. Within these tags, you can define the <method></method> and <trans-attribute></trans-attribute> tags. The <method></method> tags are used to list which methods of the bean (registered using the <ejb-name></ejb-name> tags) are handled by the container. The <trans-attribute></trans-attribute> tags are used to define the attributes for the transaction. The values for these attributes can be NotSupported, Supports, Required, RequiresNew, Mandatory, and Never.

Figure 10.12. Screen shot showing the ejb-jar.xml deployment descriptor file.

graphics/10fig12.jpg

After registering the session bean in the ejb-jar.xml file, you need to register the WebLogic-specific deployment information in the weblogic-ejb-jar.xml file (see Figure 10.13).

Figure 10.13. Screen shot showing the weblogic-ejb-jar.xml deployment descriptor file.

graphics/10fig13.jpg

Take a quick look at some of the following tags:

  • <weblogic-ejb-jar></weblogic-ejb-jar> The WebLogic-specific information is encapsulated in these tags.

  • <weblogic-enterprise-bean></weblogic-enterprise-bean> The registration information of the EJB is defined within these tags. Within the <weblogic- enterprise-bean></weblogic-enterprise-bean> tags, you should register the JNDI name for an EJB. To do this, you must use the <jndi-name></jndi-name> tags for the JNDI name of the EJB listed using the <ejb-name></ejb-name> tags.

After compiling the .class files and registering the bean in the ejb-jar.xml and weblogic-ejb-jar.xml deployment descriptor files, you need to group the .class files and the deployment descriptor files into a Java archive file. To do this, you first need to copy the deployment descriptor files into a directory named META-INF and then generate the Java archive using the command

 jar cvf stateful.jar META-INF/ com\sams\learnweblogic7\ejb\stateful\*.class  

Figure 10.14 shows that the JAR command creates a Java archive named stateful.jar containing the deployment descriptor files in the META-INF directory and the .class files of the restaurant application.

Figure 10.14. Screen shot showing the creation of the stateful.jar java archive file.

graphics/10fig14.jpg

The next step is to compile the stateful.jar Java archive using the weblogic.ejbc compiler of the WebLogic Server. To do this, use the command

 java weblogic.ejbc stateful.jar EJBStatefulDeploy.jar  

The ejbc compiler combines together the EJB classes, interfaces, and deployment descriptor files and generates a Java archive file EJBStatefulDeploy.jar. In addition, the ejbc compiler generates the client-side stub classes, server-side skeleton classes, and the EJB container implementation classes (for EJBHome and EJBObject/EJBLocalObject) after validating the bean classes and interfaces written by the bean provider.

Tip

Use the -keepgenerated option with the ejbc compiler to get the Java source files for the stub and skeleton classes. This is useful for debugging and understanding how the WebLogic Server supports the EJB architecture, especially the generation of EJBObject/EJBLocalObject implementation classes.


Now the WaiterBean stateful session bean is ready to be deployed in the EJB container of the WebLogic Server.

Deploying the Program

WebLogic Server provides three different ways to deploy EJBs:

  • Admin Console Configure a New EJB

  • Admin Console Install a New EJB

  • Manually deploying on a command prompt

Each of these methods of deploying the bean will be looked at in the following sections.

Admin Console Configure a New EJB

This method for deploying the stateful session EJB assumes that the Java source files have been compiled and the stateful.jar Java archive file is generated, but that the weblogic.ejbc compiler has not been executed to process the stateful.jar file.

Start the Admin Console and select your application's domain, as shown in Figure 10.15.

Figure 10.15. Screen shot showing the Configure a New EJB screen in the Admin Console.

graphics/10fig15.jpg

Select the Configure a New EJB option. This brings up the screen in Figure 10.16. Navigate the directory structure till you reach the location where the stateful.jar file is, and select this .jar file.

Figure 10.16. Screen shot showing the location of the Java archive file.

graphics/10fig16.jpg

In the next screen, shown in Figure 10.17, you need to define an application name for the stateful session bean that has been uploaded to the WebLogic Server in the previous step.

Figure 10.17. Screen shot showing how to define a name for the new EJB using the Admin Console.

graphics/10fig17.jpg

After uploading the EJB's JAR file, you will see either a success or an error message on the screen. Java archive files for multiple EJBs can be uploaded using this screen.

Figure 10.18 shows the newly selected EJB with the status of the Deployed column as true. Congratulations! Your stateful session EJB is now deployed and ready to be used.

Figure 10.18. Screen shot showing the deployed EJB using the Admin Console configure a new EJB method.

graphics/10fig18.jpg

Admin Console Install a New EJB

The second method to deploy an EJB is by selecting the Install a New EJB option, as shown in Figure 10.19.

Figure 10.19. Screen shot showing the Install a New EJB screen in the Admin Console.

graphics/10fig19.jpg

Next select the Java archive to upload (see Figure 10.20). This is the EJBStatefulDeploy.jar Java archive file. This step assumes that the weblogic.ejbc compiler has been executed to generate the final processed Java archive file.

Figure 10.20. Screen shot showing the uploading of a new EJB using the Admin Console.

graphics/10fig20.jpg

After uploading the EJB's JAR file, you can see either a success or an error message on the screen. Java archive files for multiple EJBs can be uploaded using this screen.

Figure 10.21 shows the newly selected EJB named EJBStatefulDeploy with the status of the Deployed column as true. The stateful session EJB is now deployed successfully.

Figure 10.21. Screen shot showing the deployed EJB using the Admin Console install a new EJB method.

graphics/10fig21.jpg

Manually Deploy on a Command Prompt

The final way to deploy an EJB is from the command prompt using the weblogic.deploy tool provided by the WebLogic Server, as shown in Figure 10.22. This step assumes that the final Java archive has been generated after executing the weblogic.ejbc compiler.

Figure 10.22. Screen shot showing the deployed EJB using weblogic.deploy tool executed manually.

graphics/10fig22.jpg

The weblogic.deploy tool accepts the following arguments:

  • -port, -username, -component

  • The command to deploy, undeploy or redeploy

  • The password of the administrator/user

  • The name of the EJB that is being deployed

  • The full path of the location of the processed (by weblogic.ejbc compiler) Java archive file

Execute the Program

Because there are two parts to the Restaurant application, the server side as well as the client-side, you will execute both of them and see their output on the screen.

After deploying the stateful session bean WaiterBean in the previous step (using any of the three methods that were discussed above), you need to start up the WebLogic server using the batch file startWebLogic.bat. This step causes the EJB container in the WebLogic Server to initialize the deployed WaiterBean bean and keep its home interface WaiterHome registered with the WebLogic Server's naming service.

Now open up another command prompt window and execute the EJB client class Customer as a standalone Java application. On executing the Customer class, you'll see the output shown in Figure 10.23 in the command prompt window of the Customer class.

Figure 10.23. Screen shot showing the output in the command prompt window of the Customer class.

graphics/10fig23.jpg

As the Customer class traverses through its workflow of actions and interacts with the WaiterBean stateful session bean, the WaiterBean generates output on the console of the WebLogic Server. This output is shown in Figure 10.24.

Figure 10.24. Screen shot showing the output of the WaiterBean in the command prompt window of the WebLogic Server Console.

graphics/10fig24.jpg



Sams Teach Yourself BEA WebLogic Server 7. 0 in 21 Days
Sams Teach Yourself BEA WebLogic Server 7.0 in 21 Days
ISBN: 0672324334
EAN: 2147483647
Year: 2002
Pages: 339

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net