How to write an EJB application that uses session beans to control the transaction scope of one or more entity beans.
See the part on developing Enterprise JavaBeans in the Programmer's Guide |
To write a session bean with bean-demarcated transactions you:
At startup, the SilverStream Server creates a transaction object. This transaction object can be accessed via the container's context. (This context is passed to the session bean when it is instantiated.) If you save the context (in the setSessionContext() method) you can call the getUserTransaction() method to obtain the transaction object.
UserTransaction utx = null; utx = m_context.getUserTransaction(); utx.begin();
For this example, the m_context is a SessionContext, and it was populated in the setSessionContext() method.
To commit a transaction, call:
utx.commit();
To rollback a transaction, call:
utx.rollback();
The following methods manage access to entity bean and wrap the bean within a transaction to limit database reads which might enhance performance:
The transferBetweenAccounts() method requires a transaction because the operation must be atomic.
Getting the session context
The m_context is declared in the declarations section as follows:
protected SessionContext m_context;
The setSessionContext() method looks like this:
public void setSessionContext(javax.ejb.SessionContext psessionContext) throws java.rmi.RemoteException { m_context = psessionContext; }
Doing a deposit
Here's how the depositToAccount() method begins, commits or rollsback a transaction.
// Find the account record for the account number passed in to //this method. EBAccount ebAccount = null; UserTransaction utx = null; try { utx = m_context.getUserTransaction(); utx.begin(); EBAccountPrimaryKey pkAccount = new EBAccountPrimaryKey(); pkAccount.m_account_number = psAccountNumber; ebAccount = (EBAccount) m_EBAccountHome.findByPrimaryKey(pkAccount); // If we didn't find it, throw an exception. if (ebAccount == null){ utx.rollback; String sErrorMessage = BankDemoConstants.MSG_NO_ACCOUNT_FOUND; throw new BankDemoException(sErrorMessage); } // This is where we call the EBAccount to make the deposit. ebAccount.accountDeposit(pbdTransactionAmount); utx.commit(); utx = null; } catch(Exception e) { // If we still have a value in utx, we need to roll it back. if (utx != null) { try { utx.rollback(); utx = null; } catch (Exception excp) {} } // If it failed, just rethrow the exception thrown by the //EBAccount. throw new BankDemoException(e.toString()); }
The container always manages an entity bean's participation in a transaction. You specify how the container handles a method by adding an entry in the deployment descriptor. At runtime, the container ensures that the methods are called within the correct transaction context based on the deployment descriptor entries.
BankDemo transaction attributes
For the BankDemo, we want the session bean to create the transaction context, and we want the entity beans to run within that context. We don't want the container to change the transaction context that the session bean has created. For this reason, we want all of the entity bean's methods to run using the Supported attribute. Using the Supported attribute will allow the container to call each method within the transaction of the caller's transaction context, that is, the SBBankATM's transaction context.
In SilverStream, you set these attributes by creating a Transaction Entry in the Application Assembly portion of the deployment descriptor shown here.
In SilverStream, all methods default to the Supports attribute, so you do not have to specify a Transaction Entry to use it. However, you might want to set it for documentation purposes.
For more information on the transaction attributes, see section 11.6.2 of the EJB Specification.
The Property Inspector for the SBBankATMBean session bean shows this:
Understanding transaction scope and propagation
For container-demarcated transactions, the container makes sure that a specific method is always executed within the appropriate transaction context based on the deployment descriptor. In the BankDemo, all methods use the Supports transaction attribute. The following diagram shows how the Session Bean SBBankATMBean controls the transaction context and the container honors that control.
Reasons why you might want to use transactions
In SilverStream, there are two reasons that you might want to control transactions from a session bean:
EJB containers provide powerful and easy to use declarative transactions. You can use a bean-demarcated session bean to gain further control of the granularity and scope of your entity bean transactions.
The SilverStream container will obtain all of the necessary database information in a single database read when the operations are enclosed in a transaction. If not, the container will request the records as it needs them. Depending on your application requirements, it might be useful to use transactions to limit database access.