Example: Developing session bean with bean managed transaction

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002
//   All Rights Reserved
//   Licensed Materials - Property of IBM
//   US Government Users Restricted Rights - Use, duplication or
//   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
//   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//   OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

import java.rmi.RemoteException;
import java.util.*;
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import javax.transaction.*;

/*************************************************************************************
* This bean is designed to demonstrate Database Connections in a                       * Bean-Managed Transaction Session Bean.  Its transaction attribute                    * should be set to TX_BEANMANAGED.                                                    
***************************************************************************************/
public class ShowEmployeesBMTBean implements SessionBean {
    private javax.ejb.SessionContext mySessionCtx = null;
    final static long serialVersionUID = 3206093459760846163L;

    private javax.sql.DataSource ds;

    private javax.transaction.UserTransaction userTran;

//************************************************************************************
//* ejbActivate calls the getDS method, which makes the JNDI lookup for the DataSource
//* Because the DataSource lookup is in a separate method, we can also invoke it from    
//* the getEmployees method in the case where the DataSource field is null.        
//************************************************************************************
public void ejbActivate() throws java.rmi.RemoteException {
    getDS();
}
/**
 * ejbCreate method 
 * @exception javax.ejb.CreateException
 * @exception java.rmi.RemoteException
 */
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.RemoteException {}
/**
 * ejbPassivate method 
 * @exception java.rmi.RemoteException
 */
public void ejbPassivate() throws java.rmi.RemoteException {}
/**
 * ejbRemove method 
 * @exception java.rmi.RemoteException
 */
public void ejbRemove() throws java.rmi.RemoteException {}

//************************************************************************************
//* The getEmployees method runs the database query to retrieve the employees.          
//* The getDS method is only called if the DataSource or userTran variables are null.
//* If a StaleConnectionException occurs, the bean retries the transaction 5 times,    
//* then throws an EJBException.                            *
//************************************************************************************

public Vector getEmployees() throws EJBException {
   Connection conn  = null;
   Statement stmt = null;
   ResultSet rs = null;
   Vector employeeList = new Vector();

   // Set retryCount to the number of times you would like to retry after a
   //StaleConnectionException"
   int retryCount = 5;  
    
   // If the Database code processes successfully, we will set error = false
   boolean error = true;
   
   if (ds == null || userTran == null) getDS();
      do {        
         try { 
              //try/catch block for UserTransaction work
              //Begin the transaction
            userTran.begin();
try { 
                 //try/catch block for database work
                 //Get a Connection object conn using the DataSource factory.
               conn = ds.getConnection();
               // Run DB query using standard JDBC coding.
               stmt = conn.createStatement();
               String query   = "Select FirstNme, MidInit, LastName " + 
                       "from Employee ORDER BY LastName";
               rs   = stmt.executeQuery(query);
               while (rs.next()) {
                  employeeList.addElement(rs.getString(3) + ", " +                                                               rs.getString(1) + " " + rs.getString(2));
               }
//Set error to false, as all database operations are successfully completed
               error = false;
            } 
            catch (com.ibm.websphere.ce.cm.StaleConnectionException se) {

// This exception indicates that the connection to the database is no longer valid.
// Rollback the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.

System.out.println("Stale Connection Exception during get connection or process SQL: " + se.getMessage());
            userTran.rollback();
            if (--retryCount == 0) {
//If we have already retried the requested number of times, throw an EJBException.
               throw new EJBException("Transaction Failure: " + se.toString());
            } 
            else {
               System.out.println("Retrying transaction, retryCount = " +                                                retryCount);
            }
         } 
         catch (com.ibm.ejs.cm.pool.ConnectionWaitTimeoutException cw) {

// This exception is thrown if a connection can not be obtained from the
// pool within a configurable amount of time.  Frequent occurrences of
// this exception indicate an incorrectly tuned connection pool

            System.out.println("Connection Wait Timeout Exception during get connection or process SQL: " + cw.getMessage());
            userTran.rollback();
            throw new EJBException("Transaction failure: " + cw.getMessage());
         } 
         catch (SQLException sq) {                   
         // This catch handles all other SQL Exceptions
      System.out.println("SQL Exception during get connection or process SQL: " +
                sq.getMessage());
            userTran.rollback();
            throw new EJBException("Transaction failure: " + sq.getMessage());
         } 
         finally {
// Always close the connection in a finally statement to ensure proper 
// closure in all cases. Closing the connection does not close and 
// actual connection, but releases it back to the pool for reuse.

            if (rs != null) {
               try {
                  rs.close();
               } 
               catch  Exception(e) {
                  System.out.println("Close Resultset Exception: " + e.getMessage());
               }
            }
            if (stmt != null) {
               try {
                  stmt.close();
 } 
            catch  Exception(e) {
               System.out.println("Close Statement Exception: " + e.getMessage());
            }
         }         
         if (conn != null) {
            try {
               conn.close();
            } 
            catch  Exception(e) {
               System.out.println("Close connection exception: " + e.getMessage());
            }
         }
      }          
      if (!error) {
         //Database work completed successfully, commit the transaction
         userTran.commit();
      }
      //Catch UserTransaction exceptions
      } 
      catch (NotSupportedException nse) {

//Thrown by UserTransaction begin method if the thread is already associated with a 
//transaction and the Transaction Manager implementation does not support nested //transactions.
 System.out.println("NotSupportedException on User Transaction begin: " +
                                 nse.getMessage());
         throw new EJBException("Transaction failure: " + nse.getMessage());
      } 
      catch (RollbackException re) {
//Thrown to indicate that the transaction has been rolled back rather than committed.
         System.out.println("User Transaction Rolled back! " + re.getMessage());
         throw new EJBException("Transaction failure: " + re.getMessage());
      } 
      catch (SystemException se) {
      //Thrown if the transaction manager encounters an unexpected error condition
         System.out.println("SystemException in User Transaction: "+ se.getMessage());
         throw new EJBException("Transaction failure: " + se.getMessage());
      } 
      catch  Exception(e) {
         //Handle any generic or unexpected Exceptions
         System.out.println("Exception in User Transaction: " + e.getMessage());
         throw new EJBException("Transaction failure: " + e.getMessage());        
      }
   } 
   while (error);
   return employeeList;
}
/**
 * getSessionContext method comment
 * @return javax.ejb.SessionContext
 */
public javax.ejb.SessionContext getSessionContext() {
    return mySessionCtx;
}

//************************************************************************************
//* The getDS method performs the JNDI lookup for the DataSource.            
//* This method is called from ejbActivate, and from getEmployees if the DataSource    
//* object is null.                                    
//************************************************************************************
private void getDS() {
   try {
      // Note the new Initial Context Factory interface available in WebSphere 4.0
      Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY, 
         "com.ibm.websphere.naming.WsnInitialContextFactory");
      InitialContext ctx = new InitialContext(parms);

      // Perform a naming service lookup to get the DataSource object.
      ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
      //Create the UserTransaction object
      userTran = mySessionCtx.getUserTransaction();
   } 
   catch  Exception(e) {
      System.out.println("Naming service exception: " + e.getMessage());
      e.printStackTrace();
}
}
/**
 * setSessionContext method
 * @param ctx javax.ejb.SessionContext
 * @exception java.rmi.RemoteException
 */
public void setSessionContext(javax.ejb.SessionContext ctx) throws java.rmi.RemoteException {
    mySessionCtx = ctx;
}
}

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002
//   All Rights Reserved
//   Licensed Materials - Property of IBM
//   US Government Users Restricted Rights - Use, duplication or
//   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
//   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//   OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * This is a Home interface for the Session Bean
 */
public interface ShowEmployeesBMTHome extends javax.ejb.EJBHome {

/**
 * create method for a session bean
 * @return WebSphereSamples.ConnPool.ShowEmployeesBMT
 * @exception javax.ejb.CreateException
 * @exception java.rmi.RemoteException
 */
WebSphereSamples.ConnPool.ShowEmployeesBMT create() throws javax.ejb.CreateException, java.rmi.RemoteException;
}

//===================START_PROLOG======================================
//
//   5630-A23, 5630-A22,
//   (C) COPYRIGHT International Business Machines Corp. 2002
//   All Rights Reserved
//   Licensed Materials - Property of IBM
//   US Government Users Restricted Rights - Use, duplication or
//   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
//   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//   OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================

package WebSphereSamples.ConnPool;

/**
 * This is an Enterprise Java Bean Remote Interface
 */
public interface ShowEmployeesBMT extends javax.ejb.EJBObject {

/**
 * 
 * @return java.util.Vector
 */
java.util.Vector getEmployees() throws java.rmi.RemoteException, javax.ejb.EJBException;
}