Transactions in WebLogic

After covering the concepts of container-managed transactions and bean-managed transactions, you will now learn about transactions in WebLogic Server, which enhances the transaction support by adding new interfaces and classes that extend the Java Transaction API. Additionally, WebLogic Server supports both container-managed and bean-managed transactions.

Container-Managed Transactions

In a container-managed transaction the container manages the transaction demarcation. In the case of a system exception, the container rolls back the transaction. However, if there is an application-level exception, the container cannot roll back the transaction. In that case, the bean developer can call the setRollbackOnly() method of the EJBContext interface to mark a transaction for rollback and protect data integrity.

Transaction-related information is maintained in the deployment descriptor that the container uses at runtime to manage the transaction. Take a closer look at each of the elements of the deployment descriptor ejb-jar.xml that need to be set in order to deploy a container-managed transaction application.

The first thing that a bean provider or application assembler needs to specify is who is going to manage the transaction. This information is specified in a transaction-type element in the ejb-jar.xml deployment descriptor. For a container-managed transaction the value specified here is Container:

 <transaction-type>Container</transaction-type>  

The transaction-related information for a function is encapsulated in the container-transaction element. This element in the ejb-jar.xml can be specified for one or more methods. It is required that all the methods that are specified in the same container-transaction element be of the same bean. Each container-transaction element consists of a list of one or more method elements, as well as the trans-attribute element. Details of these elements are as follows:

  • trans-attribute element: The bean provider specifies one of the container-managed transaction attributes in this element. The possible values can be: NotSupported, Required, Supports, RequiresNew, Mandatory, and Never. The container picks up the transaction attribute from this element and if no value is specified, it takes the default value.

  • method element: It consists of the following elements:

    • -ejb-name element Name of the entity bean.

    • -method-name element Name of the method that will participate in the transaction. * indicates that all the bean's business methods excluding the getEJBHome, getEJBLocalHome, getHandle, getPrimaryKey, and is-identical methods of the bean's component interface and getEJBMetaData and getHomeHandle methods are in the home interface.

    • -method-params element Fully qualified Java type of a method parameter. If there are multiple methods with the same name (overloaded methods) in the same interface, then this element helps to distinguish them based on the parameter types specified.

    • -method-intf element Similar to method-params, it helps differentiate overloaded methods in the same interface. Similarly to the previous element, this element helps differentiate methods with the same name and signature that are multidefined across the component or home interfaces.

Let's look at a few examples of the method element. Scenario 1: This snippet specifies the transaction attributes for all the allowable methods:

 <method>      <ejb-name>waiterEJB</ejb-name>     <method-name>*</method-name> </method> 

Scenario 2: The following snippet specifies the transaction attribute for all overloaded methods in the component and/or home interface. If the same methods are configured as in Scenario 1, then Scenario 2 takes precedence:

 <method>      <ejb-name>waiterEJB</ejb-name>     <method-name>method_in_waiterEJB</method-name> </method> 

Scenario 3: This snippet specifies the transaction attribute of the method whose parameter types are specified in the method-param element. A method can be uniquely identified from the set of overloaded methods by specifying its parameters. Scenario 3 has precedence over Scenario 2 and Scenario 1:

 <method>        <ejb-name>waiterEJB</ejb-name>       <method-name>method_in_waiterEJB</method-name>       <method-params>           <method-param>1st parameter</method-param>                  ...           <method-param>Nth parameter</method-param>       </method-params> </method> 

Scenario 4: The following snippet specifies the transaction attribute for methods defined in the remote interface:

 <method>    <ejb-name>waiterEJB</ejb-name>   <method-intf>Remote</method-intf>   <method-name>*</method-name> </method> 

Here is a sample deployment descriptor for a container-managed transaction:

 <ejb-jar>  ...    <assembly-descriptor>    ...       <container-transaction>          <method>             <ejb-name>waiterEJB</ejb-name>             <method-intf>Remote</method-intf>             <method-name>*</method-name>          </method>          <trans-attribute>Required</trans-attribute>       </container-transaction>       <container-transaction>          <method>             <ejb-name>waiterEJB</ejb-name>             <method-name>updateOrder</method-name>          </method>          <trans-attribute>Mandatory</trans-attribute>       </container-transaction>       <container-transaction>          <method>             <ejb-name>waiterEJB</ejb-name>             <method-name>*</method-name>             <method-params>                <method-param>java.lang.String</method-param>             </method-params>          </method>          <trans-attribute>RequiresNew</trans-attribute>       </container-transaction>    </assembly-descriptor> </ejb-jar> 
Entity Beans and Container-Managed Transactions

In entity beans, transactions are handled using ejbLoad() and ejbStore() methods. When a container calls the ejbLoad() method, it puts a lock on the database. When the transaction is completed, the container calls ejbStore()and releases the database lock. Therefore, a transaction begins on ejbLoad() and commits on ejbStore(). All the business methods taking part in the transaction are called between these two methods. If any of the business methods fail, the container calls ejbLoad() and refreshes the values it had before the start of the transaction.

Session Beans and Container-Managed Transactions

All the methods participating in a transaction, along with the transaction-related information, are specified in the deployment descriptor. A stateful session bean with container-managed transaction can optionally implement the javax.ejb.SessionSynchronization interface to manage synchronization of its instance variables. The methods of this interface are called by the container to notify the bean of the transaction state. The method details are as follows:

  • afterBegin() This method is called by the container to notify the bean that a new transaction has started.

  • beforeCompletion() This method is called by the container to notify the bean that a transaction is about to be finished.

  • afterCompletion() This method is called by the container to notify the bean of the transaction completion. A Boolean flag is passed to this method, indicating transaction success or failure.

Bean-Managed Transactions

In bean-managed transactions, the bean provider specifies the transaction demarcation in the bean implementation using methods in the javax.transaction.UserTransaction. The client uses JNDI to get the object reference of javax.transaction.UserTransaction. This interface has a begin() method to specify the start of the transaction, a commit() method to complete the transaction, or a rollback() method to rollback the transaction. Bean-managed transactions are only for session beans, while entity beans can only be used in container-managed transactions.

There are JTA APIs provided by Sun Microsystems Inc. for managing transactions. BEA WebLogic has extended these classes and added a few additional classes to improve transaction handling.

WebLogic Custom APIs

The details of each of the JTA custom classes and interfaces provided by BEA are described in the following sections.

The RollbackException Class
 class weblogic.transaction.RollbackException (extends javax.transaction.RollbackException)  

This class gives detailed information about exceptions and their origins. It provides overloaded printStackTrace() methods to display the original exceptions occurring due to the rollback. These methods are useful when logging error messages or for debugging.

The TransactionManager Interface
 interface weblogic.transaction.TransactionManager          (extends javax.transaction.TransactionManager) 

This interface is derived from the JTA TransactionManager interface. It allows the XA resources to register and unregister themselves with the transaction manager on startup. It also helps to resume the transaction after it has been suspended for some reason. Its methods are as follows:

  • registerStaticResource()

  • registerDynamicResource()

  • unregisterResource()

  • getTransaction()

  • forceResume()

  • forceSuspend()

  • begin()

The TransactionManager interface provides methods to resume transactions, enlist all registered resources [forceResume()], suspend a transaction, and delist all registered resources [forceSuspend()]. It can also register a new resource with the transaction service dynamically [registerDynamicResource(), registerDynamicResource(), registerStaticResource()], and remove prior resource registration [unregisterResource()]. The details of two important methods follow:

  • forceSuspend() It returns the transaction object after suspending it and delists all the resources from that transaction.

  • forceResume() It accepts the transaction object. If the transaction is active, it enlists all the resources willing to participate in the transaction, and associates the current thread with this transaction.

Here's an example:

 // Get the transaction associated with the current thread  weblogic.transaction.TransactionManager transManager =         TxHelper.getTransaction(); // suspending the transaction to perform NON-TRANSACTION       // operations         (RMI or JDBC operations) weblogic.transaction.Transaction suspendedTx =    transManager.forceSuspend(); // ... make non-transactional call ... // Again resume the Old Transaction that was suspended transManager.forceResume(suspendedTx); 
The Transaction Interface
 interface weblogic.transaction.Transaction (extends javax.transaction.Transaction)  

This interface is derived from the JTA Transaction interface. Its methods are as follows:

  • setName(), getName()

  • addProperties(), setProperty(), getProperty(), and getProperties()

  • setRollbackReason(), getRollbackReason()

  • getHeuristicErrorMessage()

  • getXID and getXid()

  • getStatusAsString()

  • getMillisSinceBegin()

  • getTimeToLiveMillis()

  • isTimedOut()

The Transaction interface provides various methods to get and set transaction-related properties, associate transaction properties (key/value pairs) with transactions throughout its life cycle [addProperties(), setProperty(), getProperty(), and getProperties()], roll back causes [setRollbackReason() and getRollbackReason()], retrieve the transaction identifier [getXID() and getXid()], get the age of the transaction time in milliseconds [getMillisSinceBegin()], obtain the amount of time in milliseconds that the transaction has left to go [getTimeToLiveMillis()], and obtain the status of the transaction timeout [isTimeout()]. Details of two important methods follow:

  • addProperties() It accepts the transaction properties in a java.util.Map object. Transaction properties are key/value pairs, associated with the transaction throughout its life cycle. The weblogic.transaction property is reserved for BEA Systems. WebLogic uses the weblogic.transaction.name key for error logging and tracing output.

  • getStatusAsString() It returns the status of the transaction in string format. Status is any one of those values defined in javax.transaction.Status.

The TxHelper Class
 class weblogic.transaction.TxHelper  

This class provides methods to get a handle to the transaction manager that is responsible for managing the current thread participating in the transaction. Its methods are as follows:

  • getTransaction()

  • getUserTransaction()

  • getTransactionManager()

  • status2String()

  • createXid()

  • getClientInterposedTransactionManager()

The TxHelper class provides methods to access the transaction, the user transaction, and the transaction manager [getTransaction(), getUserTransaction(), getTransactionManager()].

The XAResource Interface
 interface weblogic.transaction.XAResource (extends javax.transaction.xa.XAResource)  

This interface is used to communicate extra information to the transaction manager. Its methods are as follows:

  • detectedUnavailable() It returns a Boolean expression indicating whether or not the resources are up and running. The transaction manager calls this method to see if the XA resource is responsive to its calls.

  • getDelistFlag() The transaction manager calls this method to get the delist flag used in the XAResource.end() operations.

Entity Beans and Bean-Managed Transaction

Entity beans do not support bean-managed transactions since the bean provider does not have any control over the sequence in which ejbLoad() and ejbStore() methods are called.

Session Beans and Bean-Managed Transactions

A stateful session bean may not commit or roll back before the business method returns control. Therefore, if a transaction initiated by a call from the client has not completed, the container spans the same transaction across multiple calls from the same client, until the instance completes the transaction.

A stateless session bean should always have a commit or rollback at the end of a business method.

Sample Program: Implementing Transactions in the Restaurant Application

Let's work through an example that shows steps for bean-managed transaction processing using WebLogic/JTA APIs. First import all the packages required for transactions:

 import javax.transaction.UserTransaction;  import javax.transaction.SystemException; import javax.transaction.HeuristicMixedException import javax.transaction.HeuristicRollbackException import javax.transaction.NotSupportedException import javax.transaction.RollbackException import javax.transaction.IllegalStateException import javax.transaction.SecurityException import weblogic.transaction.Transaction; import weblogic.transaction.TxHelper; 

The import javax.transaction package contains classes and interfaces supplied by Sun. The import weblogic.transaction package contains classes and interfaces supplied by BEA Systems.

Next get the UserTransaction object from the transaction context.

 Context ctx = null;  Hashtable env = new Hashtable();      ...      ... // getting the context object ctx = new InitialContext(env); UserTransaction beanManagedTx = (UserTransaction) ctx.lookup("javax.transaction.UserTransaction"); 

Begin the transaction by calling the javax.transaction.UserTransaction.begin() method. All the operations that occur after this method call fall in the transaction

 beanManagedTx.begin();  

Next comes all the business logic that needs to participate in the transaction. Finally, you complete the transaction. It can be either successful or unsuccessful. If it is successful, then commit() is called:

 beanManagedTx.commit();  

If the transaction failed due to an exception, then rollback() is called:

 beanManagedTx.rollback();  

The architecture of the system now works as follows:

  1. The Customer instantiates a Waiter object.

  2. The Customer then gets the menu list and orders the items.

  3. When the method is called to confirm the order, the waiter loops through the vector of ordered items and allocates each item to a Chef. Each Chef bean is selected from the ChefBean pool. It then calls on a static method called getCookedItems from the ReceiveItemsFromQueue method, which is described a little later.

  4. The Chef creates the items after looking up the ingredients in the ItemBean pool. At the same time, it checks the availability of the items from the item table's item_quantity column. Also, an entry is made in the itemlog table, logging the item ID and the date that this item ID was ordered. In case the number of items ordered exceeds the quantity available, an error is thrown and a rollback is issued.

  5. After the items are cooked, they are returned to the Waiter.

  6. The Customer now calls serveItems() on the Waiter.

  7. The Waiter serves the items.

  8. The Customer asks for the bill. The Waiter delivers the bill.

The code in Listings 14.1 through 14.7 implements a bean-managed transaction; we show only the classes that have been added or changed. Here is one class that has changed:

  • ChefBean.java (Listing 14.1)

The classes that have been added are:

  • ItemLogHome.java(Listing 14.2)

  • ItemLogInterface.java (Listing 14.3)

  • ItemLogBean.java(Listing 14.4)

We also show the ejb-jar.xml file (Listing 14.5), the weblogic-cmp-rdbms-jar.xml file (Listing 14.6), and the weblogic-ejb-jar.xml file (Listing 14.7).

Listing 14.1 ChefBean.java
 /******************************************************************************   * Class Name   : ChefBean.java   * Description  : Class for ChefBean class. Defines the methods that can be   *                performed by the ChefBean class.   * @author Mandar S. Chitnis, Lakshmi AM, Pravin S. Tiwari.   * @version 1.1   * Copyright (c) by Sams Publishing. All Rights Reserved. *******************************************************************************/ package com.sams.learnweblogic7.ejb.cmp; import javax.naming.*; import javax.ejb.*; import java.util.*; import javax.rmi.PortableRemoteObject; import javax.ejb.CreateException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.transaction.*; public class ChefBean implements SessionBean {        private String chefId;        private static final boolean ENABLE_WEBLOGIC_LOGGING = true;        private boolean isAvailable;     private SessionContext ctx;        /**         * As per EJB Specifications, to be implemented by bean,         * Used when create is called on the remote interface         */        public void ejbCreate(){               webLogicLog("Method ejbCreate has been called");        }        // 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 Specifications, to be implemented by bean,         * Presently not being used         */        public void ejbActivate() {               webLogicLog("Method ejbActivate has been called");        }//end of ejbActivate        /**         * As per EJB Specifications, to be implemented by bean,         * Presently not being used         */        public void ejbRemove() {               webLogicLog("Method ejbRemove has been called");        }//end of ejbRemove        /**         * As per EJB Specifications, 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        /**           * Look up the bean's home interface using JNDI.           */          private ItemHome lookupHome()               throws NamingException          {               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 CMP ItemHome created "+ctx);               try {                 Object home = (ItemHome)ctx.lookup("CMP_ItemHome");                 return (ItemHome) PortableRemoteObject.narrow(home,                         ItemHome.class);               } catch (NamingException ne) {                 webLogicLog("Unable to look up the EJBHome.                         Verify the ejb JNDI name CMP_ItemHome on the WebLogic                         server");                 throw ne;               }          }        /**           * Look up the bean's home interface using JNDI.           */          private ItemLogHome lookupItemLogHome()               throws NamingException          {               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 CMP ItemHome created "+ctx);               try {                 Object home = (ItemLogHome)ctx.lookup("CMP_ItemLogHome");                 return (ItemLogHome) PortableRemoteObject.narrow(home,                         ItemLogHome.class);               } catch (NamingException ne) {                 webLogicLog("Unable to lookup the EJBHome.                         Verify the ejb JNDI name CMP_ItemLogHome on the WebLogic                         server");                 throw ne;               }          }   /**    * This method is called by the waiter to cook the item.    *    * @param orderedItem       MenuItem object ordered item    * @return                  object CookedItem    */        public CookedItemImpl cookItem(Order orderedItem) throws Exception        {               ItemHome home;               ItemLogHome logHome;               ItemPK orderedItemPk;               String EJBQLIngredients;               String orderedItemName;               String orderedItemServingSize;               String orderedItemTaste;               String orderedItemIngredients;               String orderedItemTemperature;               UserTransaction userTx = null;               webLogicLog("cook Item called");               int orderedItemId = orderedItem.getItem().getItemId();               int orderQuantity = orderedItem.getQty();               CookedItemImpl preparedItem = new CookedItemImpl();               System.out.println(                       "The ordered item desc is:"+                       orderedItem.getItem().getItemDesc());               //call the entity bean now to get the attributes for the cooked                       Item.               try{                      // *********** STARTING THE TRANSACTION *****************                      userTx = ctx.getUserTransaction();                      //(javax.transaction.UserTransaction)                      userTx.begin();                      System.out.println(                              " Bean Managed Transaction STARTED .........");                      // For demonstration purposes                              - let's assume that we first put the 'item ordered'                              and 'time' into                      // a temporary table called "itemlog".                              all the items ordered every day are entered in this                              table.                      // This table is used by the restaurant manager to find                              out what items are in demand and how many of each                              item are sold on a daily basis. In short, it gives                              total numbers of all the items.                      // that were sold every day.                      logHome = lookupItemLogHome();                      logHome.create(orderedItemId ,                              new java.sql.Date(System.currentTimeMillis ()));                      home = lookupHome();                      orderedItemPk = new ItemPK(orderedItemId);                      ItemInterface orderedItemInterface =                              (ItemInterface)home.findByPrimaryKey(orderedItemPk);                      int remainingQty = orderedItemInterface.getItemQuantity();                      orderedItemName = orderedItem.getItem().getItemDesc();                      if ((remainingQty - orderQuantity)<=0)                      {                             throw new Exception("Item "+orderedItemName+                                     " Out of Stock");                      }                      preparedItem.setItemName(orderedItemName);                      orderedItemServingSize =                              orderedItemInterface.getItemServingSize();                      preparedItem.setServingSize(orderedItemServingSize);                      orderedItemTaste = orderedItemInterface.getItemTaste();                      preparedItem.setTaste(orderedItemTaste);                      orderedItemIngredients =                              orderedItemInterface.getItemIngredients();                      preparedItem.setIngredients(orderedItemIngredients);                      orderedItemTemperature =                              orderedItemInterface.getItemTemperature();                      preparedItem.setTemperature(orderedItemTemperature);                      System.out.println(                              "Demonstration of findIngredientsByItemName:");                      ItemInterface demonstrateEJBQL =                              (ItemInterface)home.findIngredientsByItemName                              (orderedItemName);                      EJBQLIngredients = demonstrateEJBQL.getItemIngredients();                      // ********** COMMIT THE TRANSACTION *****************                      userTx.commit();                      System.out.println(                              " Bean Managed Transaction COMMITTED .........");                      System.out.println("Item ingredients obtained :");                      System.out.println();               }               catch(Exception e){                      try                      {                             // *********** ROLL BACK THE TRANSACTION                                     *****************                             userTx.rollback();                         System.out.println(                                 " Bean Managed Transaction ROLLED BACK                                 .........");                      } catch (Exception rollbackExp) {                        outputErrorMessage(                                "Transaction Rolled Back => Reason: " +                                rollbackExp);                      }                      throw e;               }               return preparedItem;        }//end of cookItem          // Demonstration of WEBLOGIC'S CUSTOM API          private void outputErrorMessage(String errorDesc) {                 String errorMessageToBeDisplayed = "";              String sep = System.getProperty( "line.separator" );                 weblogic.transaction.Transaction tx =                         weblogic.transaction.TxHelper.getTransaction();                 String txName = (tx == null) ? "null" : tx.getName();                 errorMessageToBeDisplayed = "Transaction Name: " + txName+ sep;                 errorMessageToBeDisplayed =                         errorMessageToBeDisplayed + "Error Desc => " + errorDesc                         + sep;                 System.out.println( errorMessageToBeDisplayed);          } } 
Listing 14.2 ItemLogHome.java
 /******************************************************************************   * Class Name   : ItemLogHome.java   * Description  : Interface for ItemLogHome. Defines the methods that can be   *                part of the ItemLogHome interface.   * @author Mandar S. Chitnis, Lakshmi AM, Pravin S. Tiwari.   * @version 1.1   * Copyright (c) by Sams Publishing. All Rights Reserved. *******************************************************************************/ package com.sams.learnweblogic7.ejb.cmp; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; import javax.ejb.FinderException; /**  * This is the home interface for the ItemBean.java.  * In WebLogic this is implemented by the code-generated container  * class ItemBeanC. A home interface may support one or more create  * methods, which must correspond to methods named "ejbCreate" in the EJBean.  *  */ public interface ItemLogHome extends EJBHome {   /**    * Corresponding to the ejbCreate method in the ItemLogBean.java.    *    * @return                  ItemInterface    * @exception               RemoteException    * @exception               CreateException    */   ItemLogInterface create(int itemId, java.sql.Date itemCreationDate)           throws CreateException, RemoteException;   /**    * Given a Primary Key, refreshes the EJBean from    * the persistent storage.    *    * @param primaryKey        Primary Key    * @return                  ItemInterface    * @exception               javax.ejb.FinderException    *                          if there is an error finding the bean    * @exception               java.rmi.RemoteException if there is    *                          a communications or systems failure    */   public ItemLogInterface findByPrimaryKey(ItemPK primaryKey)     throws FinderException, RemoteException; } 
Listing 14.3 ItemLogInterface.java
 /******************************************************************************   * Class Name   : ItemLogInterface.java   * Description  : Interface for ItemLogInterface. Defines the methods in the   *                ItemLogInterface interface.   * @author Mandar S. Chitnis, Lakshmi AM, Pravin S. Tiwari.   * @version 1.1   * Copyright (c) by Sams Publishing. All Rights Reserved. *******************************************************************************/ package com.sams.learnweblogic7.ejb.cmp; import java.rmi.RemoteException; import javax.ejb.EJBObject; import java.util.*; public interface ItemLogInterface extends EJBObject{        public int getItemId() throws RemoteException;        public void setItemId(int itemId) throws RemoteException;        public java.sql.Date getItemCreationDate() throws RemoteException;        public void setItemCreationDate(java.sql.Date itemCreationDate)                throws RemoteException; } 
Listing 14.4 ItemLogBean.java
 /******************************************************************************   * Class Name   : ItemLogBean.java   * Description  : Class for ItemLogBean class. Defines the methods that can be   *                performed by the ItemLogBean class.   * @author Mandar S. Chitnis, Lakshmi AM, Pravin S. Tiwari.   * @version 1.1   * Copyright (c) by Sams Publishing. All Rights Reserved. *******************************************************************************/ package com.sams.learnweblogic7.ejb.cmp; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import javax.ejb.CreateException; import javax.ejb.DuplicateKeyException; import javax.ejb.EJBException; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.FinderException; import javax.ejb.NoSuchEntityException; import javax.ejb.ObjectNotFoundException; import javax.ejb.RemoveException; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; abstract public class ItemLogBean implements EntityBean {     private EntityContext ctx;        public void setEntityContext(EntityContext ctx) {               System.out.println("setEntityContext called ");               this.ctx = ctx;        }        public void unsetEntityContext() {               System.out.println("ItemLogBean.unsetEntityContext");               this.ctx = null;        } //abstract get and set methods necessary for all container managed fields     abstract public int getItemId();     abstract public void setItemId(int itemId);        abstract public java.sql.Date getItemCreationDate();     abstract public void setItemCreationDate(java.sql.Date itemCreationDate);   /**    * This method is required by the EJB Specification    * but is not used by this example.    *    */   public void ejbActivate() {       System.out.println("ItemLogBean.ejbActivate");   }   /**    * This method is required by the EJB Specification,    * but is not used by this example.    *    */   public void ejbPassivate() {     System.out.println("ItemLogBean.ejbPassivate");   }   /**    * This method is required by the EJB Specification,    * but is not used by this example.    *    */   public void ejbLoad() {     System.out.println("ItemLogBean.ejbLoad");   }   /**    * Sets the EJBean's modified flag to false.    * set to false to "reset" the variable for the next transaction.    *    */   public void ejbStore() {     System.out.println("ItemLogBean.ejbStore");   }   /**    * This method is required by the EJB Specification    * but is not used by this example.    *    * @exception               javax.ejb.RemoveException    *                          if the EJBean does not allow removing the EJBean    */   public void ejbRemove()     throws RemoveException   {     System.out.println("ItemLogBean.ejbRemove ");   }   /**    * This method corresponds to the create method in the home interface    * "ItemHome.java".    * The parameter sets of the two methods are identical. When the client calls    * <code>ItemHome.create()</code>, the container (which in WebLogic EJB is    * also the home) allocates an instance of this EJBean and    * calls <code>ItemHome.ejbCreate()</code>.    * <p>    * For container-managed persistence, <code>ejbCreate()</code> returns    * a null, unlike the case of bean-managed    * persistence, where it returns a primary key.    *    * @param itemId                            int itemId,    * @param temperature                     String temperature    * @param taste                         String taste    * @param ingredients         String ingredients    * @param servingSize                     String servingSize    * @exception               javax.ejb.CreateException    *                          if there is a problem creating the bean    */   public ItemPK ejbCreate(int itemId, java.sql.Date itemCreationDate)     throws CreateException   {     System.out.println("ItemLogBean.ejbCreate called");     setItemId(itemId);     setItemCreationDate(itemCreationDate);     return null;  // See 9.4.2 of the EJB specification   }   /**    * This method is required by the EJB Specification,    * but is not used by this example.    *    * @param itemId                            int itemId,    * @param temperature                     String temperature    * @param taste                         String taste    * @param ingredients         String ingredients    */   public void ejbPostCreate(int itemId, java.sql.Date itemCreationDate)   {     System.out.println("ItemLogBean.ejbPostCreate (" + itemId() + ")");   }   /**    * Returns the Primary Key identifying this EJBean.    *    * @return                  int itemId    */   private String itemId() {     return "" + System.identityHashCode(this) + ", PK = " +       (String) ((ctx == null) ? "nullctx"                  : ((ctx.getPrimaryKey() == null ?                    "null" : ctx.getPrimaryKey().toString())));   } } 
Listing 14.5 ejb-jar.xml
 <?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'> <ejb-jar>   <enterprise-beans>   <session>       <ejb-name>Stateless_Session_EJB</ejb-name>       <home>com.sams.learnweblogic7.ejb.cmp.ChefHome</home>       <remote>com.sams.learnweblogic7.ejb.cmp.ChefInterface</remote>       <ejb-class>com.sams.learnweblogic7.ejb.cmp.ChefBean</ejb-class>       <session-type>Stateless</session-type>       <transaction-type>Bean</transaction-type>     </session>     <session>       <ejb-name>Stateful_Session_EJB</ejb-name>       <home>com.sams.learnweblogic7.ejb.cmp.WaiterHome</home>       <remote>com.sams.learnweblogic7.ejb.cmp.WaiterInterface</remote>       <ejb-class>com.sams.learnweblogic7.ejb.cmp.WaiterBean</ejb-class>       <session-type>Stateful</session-type>       <transaction-type>Container</transaction-type>     </session>     <entity>       <ejb-name>ContainerManagedEntityBean</ejb-name>       <home>com.sams.learnweblogic7.ejb.cmp.ItemHome</home>       <remote>com.sams.learnweblogic7.ejb.cmp.ItemInterface</remote>       <ejb-class>com.sams.learnweblogic7.ejb.cmp.ItemBean</ejb-class>       <persistence-type>Container</persistence-type>       <prim-key-class>com.sams.learnweblogic7.ejb.cmp.ItemPK</prim-key-class>       <reentrant>False</reentrant>       <cmp-version>2.x</cmp-version>       <abstract-schema-name>Item</abstract-schema-name>       <cmp-field>         <field-name>itemId</field-name>       </cmp-field>       <cmp-field>         <field-name>itemDesc</field-name>       </cmp-field>       <cmp-field>         <field-name>itemTaste</field-name>       </cmp-field>       <cmp-field>         <field-name>itemTemperature</field-name>       </cmp-field>       <cmp-field>         <field-name>itemIngredients</field-name>       </cmp-field>       <cmp-field>         <field-name>itemServingSize</field-name>       </cmp-field>       <cmp-field>         <field-name>itemQuantity</field-name>       </cmp-field>       <query>         <query-method>           <method-name>findIngredientsByItemName</method-name>           <method-params>             <method-param>java.lang.String</method-param>           </method-params>         </query-method>         <ejb-ql>           <![CDATA[SELECT OBJECT(a) FROM Item AS a WHERE a.itemDesc = ?1]]>         </ejb-ql>       </query>     </entity>     <entity>       <ejb-name>ContainerManagedEntityLogBean</ejb-name>       <home>com.sams.learnweblogic7.ejb.cmp.ItemLogHome</home>       <remote>com.sams.learnweblogic7.ejb.cmp.ItemLogInterface</remote>       <ejb-class>com.sams.learnweblogic7.ejb.cmp.ItemLogBean</ejb-class>       <persistence-type>Container</persistence-type>       <prim-key-class>com.sams.learnweblogic7.ejb.cmp.ItemPK</prim-key-class>       <reentrant>False</reentrant>       <cmp-version>2.x</cmp-version>       <abstract-schema-name>LogItem</abstract-schema-name>       <cmp-field>         <field-name>itemId</field-name>       </cmp-field>       <cmp-field>         <field-name>itemCreationDate</field-name>       </cmp-field>     </entity>   </enterprise-beans>   <assembly-descriptor>     <container-transaction>       <method>         <ejb-name>Stateful_Session_EJB</ejb-name>        <method-name>*</method-name>       </method>       <method>         <ejb-name>ContainerManagedEntityBean</ejb-name>        <method-name>*</method-name>       </method>       <method>         <ejb-name>ContainerManagedEntityLogBean</ejb-name>        <method-name>*</method-name>       </method>       <trans-attribute>Required</trans-attribute>     </container-transaction>   </assembly-descriptor> <ejb-client-jar>CMPClient.jar</ejb-client-jar> </ejb-jar> 
Listing 14.6 weblogic-cmp-rdbms-jar.xml
 <!DOCTYPE weblogic-rdbms-jar PUBLIC  '-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB RDBMS Persistence//EN'  'http://www.bea.com/servers/wls600/dtd/weblogic-rdbms20-persistence-600.dtd'> <weblogic-rdbms-jar>   <weblogic-rdbms-bean>     <ejb-name>ContainerManagedEntityBean</ejb-name>     <data-source-name>ejb-datasource-learnweblogic7</data-source-name>     <table-name>item</table-name>     <field-map>       <cmp-field>itemId</cmp-field>       <dbms-column>item_id</dbms-column>     </field-map>     <field-map>       <cmp-field>itemDesc</cmp-field>       <dbms-column>item_desc</dbms-column>     </field-map>     <field-map>       <cmp-field>itemIngredients</cmp-field>       <dbms-column>item_ingredients</dbms-column>     </field-map>     <field-map>       <cmp-field>itemTemperature</cmp-field>       <dbms-column>item_temperature</dbms-column>     </field-map>     <field-map>       <cmp-field>itemServingSize</cmp-field>       <dbms-column>item_serving_size</dbms-column>     </field-map>     <field-map>       <cmp-field>itemTaste</cmp-field>       <dbms-column>item_taste</dbms-column>     </field-map>     <field-map>       <cmp-field>itemQuantity</cmp-field>       <dbms-column>item_quantity</dbms-column>     </field-map>    </weblogic-rdbms-bean>   <weblogic-rdbms-bean>     <ejb-name>ContainerManagedEntityLogBean</ejb-name>     <data-source-name>ejb-datasource-learnweblogic7</data-source-name>     <table-name>itemlog</table-name>     <field-map>       <cmp-field>itemId</cmp-field>       <dbms-column>item_id</dbms-column>     </field-map>     <field-map>       <cmp-field>itemCreationDate</cmp-field>       <dbms-column>item_creation_date</dbms-column>     </field-map>   </weblogic-rdbms-bean>   <create-default-dbms-tables>True</create-default-dbms-tables> </weblogic-rdbms-jar> 
Listing 14.7 weblogic-ejb-jar.xml
 <?xml version="1.0"?> <!DOCTYPE weblogic-ejb-jar PUBLIC "-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN" "http://www.bea.com/servers/wls600/dtd/weblogic-ejb-jar.dtd" > <weblogic-ejb-jar>   <weblogic-enterprise-bean>     <ejb-name>Stateless_Session_EJB</ejb-name>     <jndi-name>Chef_Home</jndi-name>   </weblogic-enterprise-bean>   <weblogic-enterprise-bean>     <ejb-name>Stateful_Session_EJB</ejb-name>     <jndi-name>Waiter_Home</jndi-name>   </weblogic-enterprise-bean>   <weblogic-enterprise-bean>     <ejb-name>ContainerManagedEntityBean</ejb-name>     <entity-descriptor>       <persistence>         <persistence-type>          <type-identifier>WebLogic_CMP_RDBMS</type-identifier>          <type-version>6.0</type-version>          <type-storage>META-INF/weblogic-cmp-rdbms-jar.xml</type-storage>        </persistence-type>        <persistence-use>          <type-identifier>WebLogic_CMP_RDBMS</type-identifier>          <type-version>6.0</type-version>        </persistence-use>       </persistence>     </entity-descriptor>     <jndi-name>CMP_ItemHome</jndi-name>   </weblogic-enterprise-bean>   <weblogic-enterprise-bean>     <ejb-name>ContainerManagedEntityLogBean</ejb-name>     <entity-descriptor>       <persistence>         <persistence-type>          <type-identifier>WebLogic_CMP_RDBMS</type-identifier>          <type-version>6.0</type-version>          <type-storage>META-INF/weblogic-cmp-rdbms-jar.xml</type-storage>        </persistence-type>        <persistence-use>          <type-identifier>WebLogic_CMP_RDBMS</type-identifier>          <type-version>6.0</type-version>        </persistence-use>       </persistence>     </entity-descriptor>     <jndi-name>CMP_ItemLogHome</jndi-name>   </weblogic-enterprise-bean> </weblogic-ejb-jar> 

The code for a container-managed transaction is shown in Listing 14.8. Only ChefBean is displayed, since only the ChefBean is different from the code for a bean-managed transaction. The ejb-jar.xml and file are also shown in Listing 14.9.

Listing 14.8 ChefBean.java
 /******************************************************************************   * Class Name   : ChefBean.java   * Description  : Class for ChefBean class. Defines the methods that can be   *                performed by the ChefBean class.   * @author Mandar S. Chitnis, Lakshmi AM, Pravin S. Tiwari.   * @version 1.1   * Copyright (c) by Sams Publishing. All Rights Reserved. *******************************************************************************/ package com.sams.learnweblogic7.ejb.cmp; import javax.naming.*; import javax.ejb.*; import java.util.*; import javax.rmi.PortableRemoteObject; import javax.ejb.CreateException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.naming.InitialContext; import javax.naming.NamingException; public class ChefBean implements SessionBean {        private String chefId;        private static final boolean ENABLE_WEBLOGIC_LOGGING = true;        private boolean isAvailable;     private SessionContext ctx;        /**         * As per EJB Specifications to be implemented by bean,         * Used when create is called on the remote interface         */        public void ejbCreate(){               webLogicLog("Method ejbCreate has been called");        }        // 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 Specifications to be implemented by bean,         * Presently not being used         */        public void ejbActivate() {               webLogicLog("Method ejbActivate has been called");        }//end of ejbActivate        /**         * As per EJB Specifications to be implemented by bean,         * Presently not being used         */        public void ejbRemove() {               webLogicLog("Method ejbRemove has been called");        }//end of ejbRemove        /**         * As per EJB Specifications 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        /**           * Look up the bean's home interface using JNDI.           */          private ItemHome lookupHome()               throws NamingException          {               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 CMP ItemHome created "+ctx);               try {                 Object home = (ItemHome)ctx.lookup("CMP_ItemHome");                 return (ItemHome) PortableRemoteObject.narrow(home,                         ItemHome.class);               } catch (NamingException ne) {                 webLogicLog("Unable to lookup the EJBHome.                         Verify the ejb JNDI name CMP_ItemHome on the WebLogic                         server");                 throw ne;               }          }        /**           * Look up the bean's home interface using JNDI.           */          private ItemLogHome lookupItemLogHome()               throws NamingException          {               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 CMP ItemHome created "+ctx);               try {                 Object home = (ItemHome)ctx.lookup("CMP_ItemLogHome");                 return (ItemLogHome) PortableRemoteObject.narrow(home,                         ItemHome.class);               } catch (NamingException ne) {                 webLogicLog("Unable to lookup the EJBHome.                         Verify the ejb JNDI name CMP_ItemLogHome on the WebLogic                         server");                 throw ne;               }          }   /**    * This method is called by the waiter to cook the item.    *    * @param orderedItem       MenuItem object ordered item    * @return                  object CookedItem    */        public CookedItemImpl cookItem(Order orderedItem)        {               ItemHome home;               ItemLogHome logHome;               ItemPK orderedItemPk;               String EJBQLIngredients;               String orderedItemName;               String orderedItemServingSize;               String orderedItemTaste;               String orderedItemIngredients;               String orderedItemTemperature;               UserTransaction userTx;               webLogicLog("cook Item called");               int orderedItemId = orderedItem.getItem().getItemId();               int orderQuantity = orderedItem.getQty();               CookedItemImpl preparedItem = new CookedItemImpl();               System.out.println("The ordered item desc is:"+                       orderedItem.getItem().getItemDesc());               //call the entity bean now to get the attributes for the cooked                       Item.               try{                      // *********** STARTING THE TRANSACTION *****************                      //userTx = (UserTransaction)ctx.lookup(                              "javax.transaction.UserTransaction");                      //userTx.begin();                      System.out.println(                              " Container-Managed Transaction STARTED                              .........");                      // For demonstration purposes, let's assume that we first                              put the 'item ordered' and 'time' into a temporary                              table called "itemlog". All the items ordered every                              day are entered in this table.                      // This table is used by the restaurant manager to find                              out what items are in demand and how many of each                              item are sold on a daily basis. In short, it gives                              total numbers of all the items.                      // that were sold every day.                      logHome = lookupItemLogHome();                      logHome.create(orderedItemId ,                              new java.sql.Date(System.currentTimeMillis ()));                      home = lookupHome();                      orderedItemPk = new ItemPK(orderedItemId);                      ItemInterface orderedItemInterface =                              (ItemInterface)home.findByPrimaryKey(orderedItemPk);                      int remainingQty = orderedItemInterface.getItemQuantity();                      orderedItemName = orderedItem.getItem().getItemDesc();                      if ((remainingQty - orderQuantity)<=0)                      {                             System.out.println(                                     "Item "+orderedItemName+" Out of Stock");                             throw new Exception("Item "+orderedItemName+                                     " Out of Stock");                      }                      preparedItem.setItemName(orderedItemName);                      orderedItemServingSize =                              orderedItemInterface.getItemServingSize();                      preparedItem.setServingSize(orderedItemServingSize);                      orderedItemTaste = orderedItemInterface.getItemTaste();                      preparedItem.setTaste(orderedItemTaste);                      orderedItemIngredients =                              orderedItemInterface.getItemIngredients();                      preparedItem.setIngredients(orderedItemIngredients);                      orderedItemTemperature =                              orderedItemInterface.getItemTemperature();                      preparedItem.setTemperature(orderedItemTemperature);                      System.out.println(                              "Demonstration of findIngredientsByItemName:");                      ItemInterface demonstrateEJBQL =                              (ItemInterface)home.findIngredientsByItemName                              (orderedItemName);                      EJBQLIngredients = demonstrateEJBQL.getItemIngredients();                      // *********** COMMIT THE TRANSACTION *****************                      //userTx.commit();                      System.out.println( " Container-Managed Transaction COMMITTED .........");                      System.out.println("Item ingredients obtained :");                      System.out.println();               }               catch(Exception e){                      throw e;               }               return preparedItem;        }//end of cookItem } 
Listing 14.9 ejb-jar.xml
 <?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'> <ejb-jar>   <enterprise-beans>   <session>       <ejb-name>Stateless_Session_EJB</ejb-name>       <home>com.sams.learnweblogic7.ejb.cmp.ChefHome</home>       <remote>com.sams.learnweblogic7.ejb.cmp.ChefInterface</remote>       <ejb-class>com.sams.learnweblogic7.ejb.cmp.ChefBean</ejb-class>       <session-type>Stateless</session-type>       <transaction-type>Container</transaction-type>     </session>     <session>       <ejb-name>Stateful_Session_EJB</ejb-name>       <home>com.sams.learnweblogic7.ejb.cmp.WaiterHome</home>       <remote>com.sams.learnweblogic7.ejb.cmp.WaiterInterface</remote>       <ejb-class>com.sams.learnweblogic7.ejb.cmp.WaiterBean</ejb-class>       <session-type>Stateful</session-type>       <transaction-type>Container</transaction-type>     </session>     <entity>       <ejb-name>ContainerManagedEntityBean</ejb-name>       <home>com.sams.learnweblogic7.ejb.cmp.ItemHome</home>       <remote>com.sams.learnweblogic7.ejb.cmp.ItemInterface</remote>       <ejb-class>com.sams.learnweblogic7.ejb.cmp.ItemBean</ejb-class>       <persistence-type>Container</persistence-type>       <prim-key-class>com.sams.learnweblogic7.ejb.cmp.ItemPK</prim-key-class>       <reentrant>False</reentrant>       <cmp-version>2.x</cmp-version>       <abstract-schema-name>Item</abstract-schema-name>       <cmp-field>         <field-name>itemId</field-name>       </cmp-field>       <cmp-field>         <field-name>itemDesc</field-name>       </cmp-field>       <cmp-field>         <field-name>itemTaste</field-name>       </cmp-field>       <cmp-field>         <field-name>itemTemperature</field-name>       </cmp-field>       <cmp-field>         <field-name>itemIngredients</field-name>       </cmp-field>       <cmp-field>         <field-name>itemServingSize</field-name>       </cmp-field>       <cmp-field>         <field-name>itemQuantity</field-name>       </cmp-field>       <query>         <query-method>           <method-name>findIngredientsByItemName</method-name>           <method-params>             <method-param>java.lang.String</method-param>           </method-params>         </query-method>         <ejb-ql>           <![CDATA[SELECT OBJECT(a) FROM Item AS a WHERE a.itemDesc = ?1]]>         </ejb-ql>       </query>     </entity>     <entity>       <ejb-name>ContainerManagedEntityLogBean</ejb-name>       <home>com.sams.learnweblogic7.ejb.cmp.ItemLogHome</home>       <remote>com.sams.learnweblogic7.ejb.cmp.ItemLogInterface</remote>       <ejb-class>com.sams.learnweblogic7.ejb.cmp.ItemLogBean</ejb-class>       <persistence-type>Container</persistence-type>       <prim-key-class>com.sams.learnweblogic7.ejb.cmp.ItemPK</prim-key-class>       <reentrant>False</reentrant>       <cmp-version>2.x</cmp-version>       <abstract-schema-name>LogItem</abstract-schema-name>       <cmp-field>         <field-name>itemId</field-name>       </cmp-field>       <cmp-field>         <field-name>itemCreationDate</field-name>       </cmp-field>     </entity>   </enterprise-beans>   <assembly-descriptor>     <container-transaction>       <method>         <ejb-name>Stateless_Session_EJB</ejb-name>        <method-name>cookItem</method-name>       </method>       <method>         <ejb-name>Stateful_Session_EJB</ejb-name>        <method-name>*</method-name>       </method>       <method>         <ejb-name>ContainerManagedEntityBean</ejb-name>        <method-name>*</method-name>       </method>       <method>         <ejb-name>ContainerManagedEntityLogBean</ejb-name>        <method-name>*</method-name>       </method>       <trans-attribute>Required</trans-attribute>     </container-transaction>   </assembly-descriptor> <ejb-client-jar>CMPClient.jar</ejb-client-jar> </ejb-jar> 


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