Show TOC

Procedure documentationUsing Component-Managed JTA Transactions Locate this document in the navigation structure

 

The JTA standard enables you to demarcate transactions programmatically in your application code. With this approach, your component is fully in charge of starting and completing the transaction. Since correct transaction execution is important for the proper functioning of both the component and the whole application, you should use component-managed transactions carefully, when you are certain that you know the requirements of the relevant Java EE standards.

The use of component-managed JTA transactions is provided by the javax.transaction.UserTransaction interface. It enables the application component to start and complete transactions. Note that an instance of this interface does not represent a transaction object itself. The interface only provides a way for the application to tell the Transaction Service to start a new transaction for it, and later to commit or roll it back. The Transaction Service is responsible for creating the transaction object itself, which is an instance of javax.transaction.Transaction. The Transaction object is associated to the thread in which the component methods are invoked. The Transaction Service manages the transaction synchronization and the two-phase commit.

More information: Two-Phase Commit

The use of the UserTransaction interface is restricted to certain types of application components. You can look up a UserTransaction from the following components:

  • Stateless session beans with bean-managed transaction demarcation

  • Stateful session beans with bean-managed transaction demarcation

  • Message-driven beans with bean-managed transaction demarcation

  • Servlets

  • JavaServer Pages (JSPs)

You cannot use component-managed transactions with:

  • Session beans with container-managed transaction demarcation

  • Java clients

The interface provides the following methods:

  • begin() — demarcates the beginning of the transaction

  • commit() — demarcates the end of the transaction, and the modified data is stored in the database

  • getStatus() — obtains the status of the transaction; JTA defines the following transaction status types:

    • STATUS_ACTIVE — a transaction is running

    • STATUS_COMMITTED — the transaction has committed

    • STATUS_COMMITTING — the transaction is currently committing

    • STATUS_MARKED_ROLLBACK — the transaction has been set for rollback

    • STATUS_NO_TRANSACTION — there is no active transaction

    • STATUS_PREPARED — the transaction has prepared to commit (after the first phase of the two-phase commit)

    • STATUS_PREPARING — the transaction is preparing to commit

    • STATUS_ROLLEDBACK — the transaction has rolled back

    • STATUS_ROLLING_BACK — the transaction is currently rolling back

    • STATUS_UNKNOWN — there is an active transaction but its status cannot be determined

  • rollback() — demarcates the end of the transaction; the modifications made during the transaction are discarded and the data remains unchanged

  • setRollbackOnly() — marks the transaction for rollback

    Note Note

    When using component-managed transactions, you can only use UserTransaction.setRollbackOnly(). Invoking javax.ejb.EJBContext.setRollbackOnly() is an illegal operation.

    End of the note.
  • setTransactionTimeout() — enables you to set a timeout for the transaction

    Note Note

    If you do not call this method in your application, the system uses the default timeout of 24 hours. We recommend that you set a shorter timeout for the transactions you use.

    End of the note.

For more information about the UserTransaction interface, refer to the Java EE API documentation at SUN Microsystems official web site http://java.sun.com.

Prerequisites

To use component-managed JTA transaction, you must add jta.jar to the build path of the application component.

Procedure

To demarcate a component-managed transaction, you must complete the following steps:

  1. Look up the UserTransaction.

    In the AS Java the UserTransaction is looked up from the java:comp/ environment without specifying parameters in the initial naming context.

    Syntax Syntax

    1. InitialContext ctx = new InitialContext();
      UserTransaction ut = null;
      ut = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
      
    End of the code.

    For session and message-driven, beans the UserTransaction is available through their EJBContext.

    Syntax Syntax

    1. MessageDrivenContext context;
      UserTransaction ut = null;
      public void setMessageDrivenContext(MessageDrivenContext context){
      	this.context = context;
      	ut = context.getUserTransaction();
      ...
      }
    End of the code.

    Perform the lookup early in the component's life cycle — for example, in the setEJBContext() method for enterprise beans, or in the init() method for Web components. This guarantees that you have a UserTransaction reference when the component needs to start a transaction.

  2. Look up the connection factory that you use to create a connection to the underlying data store. For example, the connection factory may be a DataSource, PersistenceManagerFactory, or an instance of javax.resource.cci.ConnectionFactory.

    Syntax Syntax

    1. InitialContext ctx = new InitialContext();
      DataSource dataSource =(DataSource) ctx.lookup("java:comp/env/PERSISTENCE_EXAMPLE");
      
    End of the code.

    Look up the connection factory early in the component's life cycle. Typically, you can do that in the same method where you look up the UserTransaction.

  3. Start a transaction by calling UserTransaction.begin(), and obtain a connection from the connection factory by calling its getConnection() method.

    Call these methods before entering the methods that actually access the data store. In an enterprise bean, call the methods in the ejbCreate() method. In a Web component, invoke them in the service method, but before you have called any methods that access the database.

    Syntax Syntax

    1. protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
      	ut.begin(); 
      	dataSource.getConnection();
      
      	// Invoke the methods that work with the database 
      ...
      }
    End of the code.
  4. Close the connection after you finish working with the data store by calling connection.close(). If you use a JDBC connection, also close the statements before closing the connection.

    If you leave the connection open, the underlying physical connection may not be returned to the connection pool, which leads to resource leaks. In addition, if you do not close the connection handle and leave the used statements open, the connection handle may be reassociated to a different physical connection in the next transaction, and the state of the statements may not be consistent. Therefore, you must always close the statements and the connection before completing the transaction.

  5. Complete the transaction by calling UserTransaction.commit() or UserTransaction.rollback(). Typically, you should commit the transaction if no errors have occurred, and roll it back otherwise.

    Syntax Syntax

    1. try {
      	ut.begin();
      
      	//perform functionality
      
      	ut.commit();
      
      } catch (Exception exc) {
      	exc.printStackTrace();
      		try {
      
      		// check transaction status
      		if (ut.getStatus() != Status.STATUS_NO_TRANSACTION) {
      
      			// rollback the transaction
      			ut.rollback();
      		}
      	} catch (Exception e) {
      		e.printStackTrace();
      	}
      
    End of the code.

    When using the component-managed transaction scenario with stateless session beans, you cannot span the transaction through several business methods. For this type of enterprise beans, the EJB specification requires the transaction in which a business method is executed to be completed before the method returns. Therefore, component-managed transactions are practically useless for stateless session beans.

Example

A scenario where you can use the component-managed transaction contract is when you access the data store from a stateful session bean, or directly from a Web component. In this case, you can program your application in a way that enables several methods to change the data in a single transaction.

A typical example is a session bean that represents a client session to a shopping cart. The bean uses a single transaction to initialize the cart, add or remove items, and finally confirm the entries, or discard all changes — that is, it either commits or rolls back the transaction. Using bean-managed transactions in this scenario reduces the number of database accesses during the client session, which increases performance. The data is changed only once — that is, when the transaction commits.