In a bean-managed transaction (BMT), the code in the session or message-driven bean explicitly marks the boundaries of the transaction. An entity bean CANNOT have bean-managed transactions, it must use container-managed transactions. When you code a bean-managed transaction for session or message-driven beans, you typically can use JTA transactions.
For JTA transactions, you can invoke the begin(), commit(), and rollback() methods of the javax.transaction.UserTransaction interface. The begin() and commit() methods mark the transaction boundaries. If the transaction operations fail, an exception handler typically invokes the rollback() method, and throws an EJBException. The following code shows how to use the JTA javax.transaction.UserTransaction interface to perform a bean-managed transaction:
UserTransaction ut = context.getUserTransaction(); try { ut.begin(); // Do whatever transaction functionality is necessary ut.commit(); } catch (Exception ex) { try { ut.rollback(); } catch (SystemException syex) { throw new EJBException("Rollback failed: " + syex.getMessage()); } throw new EJBException("Transaction failed: " + ex.getMessage()); }
In a stateless session bean with bean-managed transactions, a business method MUST commit or roll back a transaction before returning. However, a stateful session bean does not have this restriction. In a stateful session bean with a JTA transaction, the association between the bean instance and the transaction is retained across multiple client calls. Even if each business method called by the client opens and closes the database connection, the association is retained until the instance completes the transaction.
There is one method limitation with JTA bean-managed transactions: do NOT invoke the getRollbackOnly() and setRollbackOnly() methods of the EJBContext interface interface in bean-managed transactions (BMT), these methods should be used ONLY in container-managed transactions (CMT). For bean-managed transactions, invoke the getStatus() and rollback() methods of the UserTransaction interface instead. And, be sure not to invoke any resource-specific functions that conflict with the transactional semantics.
Using component-managed (bean-managed) transactions
NOTE: Entity Beans CANNOT manage transactions (so CANNOT use bean-managed transactions).
To enable a session bean, servlet, or application client component to use component-managed transactions, complete the following steps:
For Session Beans, set the Transaction type attribute in the component's deployment descriptor to Bean.
For Application Client components, enable support for transaction demarcation by setting the Allow JTA Demarcation attribute in the component's deployment descriptor.
Write the component code to actively manage transactions.
For Stateful Session Beans, a transaction started in a given method does not need to be completed (that is, committed or rolled back) before completing that method. The transaction can be completed at a later time, for example on a subsequent call to the same method, or even within a different method. However, constructing the application so a transaction is begun and completed within the same method call is usually preferred, because it simplifies application debugging and maintenance.
The following code extract shows the standard code required to obtain an object encapsulating the transaction context, and involves the following basic steps:
A javax.transaction.UserTransaction object is created by calling a lookup on "java:comp/UserTransaction".
The UserTransaction object is used demarcate the boundary of a transaction by using transaction methods such as begin and commit as needed. If an application component begins a transaction, it must also complete that transaction either by invoking the commit method or the rollback method.
Code example: Getting an object that encapsulates a transaction context:
public float doSomething()throws NamingException { InitialContext initCtx = new InitialContext(); UserTransaction userTran = (UserTransaction)initCtx.lookup( "java:comp/UserTransaction"); //Use userTran object to call transaction methods userTran.begin(); //Do transactional work ... userTran.commit(); ... }
package javax.transaction; import java.lang.IllegalArgumentException; import java.lang.IllegalStateException; import java.lang.SecurityException; /** * The UserTransaction interface defines the methods that allow an * application to explicitly manage transaction boundaries. */ public interface UserTransaction { void begin() throws NotSupportedException, SystemException; void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException; void rollback() throws IllegalStateException, SecurityException, SystemException; void setRollbackOnly() throws IllegalStateException, SystemException; int getStatus() throws SystemException; void setTransactionTimeout(int seconds) throws SystemException; }