Sun Java logo     Previous      Contents      Index      Next     

Sun logo
Sun Java System Application Server Standard and Enterprise Edition 7 2004Q2 Developer's Guide to Enterprise JavaBeans Technology 

Chapter 6
Handling Transactions with Enterprise Beans

This section describes the transaction support built into the Enterprise JavaBeans (EJBs) programming model for Sun Java System Application Server.


Note

If you are unfamiliar with transaction handling in the EJB technology, refer to the Java Software tutorials:

http://java.sun.com/j2ee/docs.html

Extensive information on EJB transaction support is contained in Chapter 17, “Support for Transactions,” of the Enterprise JavaBeans Specification, v2.0.

Overview material on the Sun Java System Application Server is contained in Sun Java System Application Server and Enterprise JavaBeans Technology and the Sun Java System Application Server Product Introduction.


This section addresses the following topics:


JTA and JTS Transaction Support

J2EE includes support for distributed transactions through two specifications:

The JTA is a high-level, implementation-independent protocol API that allows applications and application servers to access transactions.

JTS specifies the implementation of a transaction manager which supports the JTA and implements the Java mapping of the OMG Object Transaction Service (OTS) 1.1 specification at the level below the API. JTS propagates transactions using the Internet Inter-ORB Protocol (IIOP).

The current transaction manager implementation supports JTS and the JTA. The EJB container itself uses the Java Transaction API interface to interact with JTS.

The J2EE transaction manager controls all EJB transactions, except for bean-managed Java Database Connectivity (JBDC) transactions, and allows an enterprise bean to update multiple databases within a transaction.


About Transaction Handling

As a developer, you can write an application that updates data in multiple databases which may be distributed across multiple sites. The site may use EJB servers from different vendors.

This section provides overview information on the following topics:

Flat Transactions

The Enterprise JavaBeans Specification, v2.0 requires support for flat (as opposed to nested) transactions. In a flat transaction, each transaction is decoupled from and independent of other transactions in the system. You cannot start another transaction in the same thread until the current transaction ends.

Flat transactions are the most prevalent model and are supported by most commercial database systems. Although nested transactions offer a finer granularity of control over transactions, they are supported by far fewer commercial database systems.

Global and Local Transactions

Understanding the distinction between global and local transactions is crucial in understanding the Sun Java System Application Server support for transactions.

Both local and global transactions are demarcated using the javax.transaction.UserTransaction interface, which the client must use. Local transactions bypass the transaction manager and are faster.

Initially, all transactions are local. If a non-XA data source connection is the first resource connection enlisted in a transaction scope, it will become a global transaction when a (second) XA data source connection joins it. If a second non-XA data source connection attempts to join, an exception is thrown.

The Sun Java System Application Server operates in either global or local transaction mode, but the two modes cannot be mixed in the same transaction.


Note

If your application uses global transactions, you must configure and enable the corresponding Sun Java System Application Server resource managers. For more information, see the Sun Java System Application Server Administration interface online help and the and Administration Guide.


Demarcation Models

As a developer, you can choose between using programmatic transaction demarcation in the EJB code (bean-managed) or declarative demarcation (container-managed). Regardless of whether an enterprise bean uses bean-managed or container-managed transaction demarcation, the burden of implementing transaction management is on the EJB container and the Sun Java System Application Server. The container and the server implement the necessary low-level transaction protocols, such as the two-phase commit protocol between a transaction manager and a dustbowls system or Sun Java System Message Queue, transaction context propagation, and distributed two-phase commit.

These demarcation models are addressed in the following sections:

Container-Managed Transactions

One primary advantage of enterprise beans is the support they provide for container-managed transactions, also known as declarative transactions. In an enterprise bean with container-managed transactions, the EJB container sets the boundaries of the transactions.


Note

You can use container-managed transactions with any type of enterprise bean (session, entity, or message-driven), but an entity bean can only use container-managed transactions.


Container-managed transactions simplify development because the EJB code does not explicitly mark the transaction's boundaries. That is, the code does not include statements that begin and end the transaction. The container is responsible for:

Bean-Managed Transactions

The EJB specification supports bean-managed transaction demarcation, also known as programmer-demarcated transactions, using javax.transaction.UserTransaction. With bean-managed transactions, you must perform a Java Naming and Directory Interface (JNDI) lookup to obtain a UserTransaction object.


Note

You can use bean-managed transactions with session or message-driven beans, but an entity bean must use container-managed transactions.


There are two types of bean-managed transactions:

Commit Options

The EBJ protocol is designed to give the container the flexibility to select the disposition of the instance state at the time a transaction is committed. This allows the container to best manage caching an entity object’s state and associating an entity object identity with the EJB instances.

There are three commit-time options:

The Sun Java System Application Server deployment descriptor has an element, commit-option, that specifies the commit option to be used. Based on the specified commit option, the appropriate handler is instantiated.


Note

It is assumed that if commit option A is used, the developer is responsible for ensuring that only this application is updating the database. In other words, this is not the container's responsibility.


Administration and Monitoring

An administrator can control the following instance-wide transaction service attributes for the transaction-service element in the server.xml file:

For further explanation on these attributes, refer to the Sun Java System Application Server Administrator’s Configuration File Reference.

In addition, the administrator can monitor transactions using statistics from the transaction manager that provide information on such activities as the number of transactions completed/rolled back/recovered since server startup, and transactions presently being processed.

For information on administering and monitoring transactions, see the Sun Java System Application Server Administration interface online help and the Sun Java System Application Server Administration Guide.


Using Container-Managed Transactions

Typically, the container begins a transaction immediately before an EJB method starts, and commits the transaction just before the method exits. Each method can be associated with a single transaction.


Note

Nested or multiple transactions are not allowed within a method.


Container-managed transactions do not require all methods to be associated with transactions. When deploying an enterprise bean, you specify which of the bean's methods are associated with transactions by setting the transaction attributes.

Although beans with container-managed transactions require less coding, they have one limitation:

If this limitation will make coding your bean difficult, bean-managed transactions may be your best choice.

When a commit occurs, the transaction signals the container that the bean has completed its useful work and tells the container to synchronize its state with the underlying data source. The container permits the transaction to complete and then frees the bean. Result sets associated with a committed transaction are no longer valid. Subsequent requests for the same bean cause the container to issue a load to synchronize state with the underlying data source.


Note

Transactions initiated by the container are implicitly committed.


Any participant can roll back a transaction.

The following sections are related to developing enterprise beans with container-managed transactions:

Specifying Transaction Attributes

A transaction attribute is a parameter that controls the scope of a transaction.

Because transaction attributes are stored in the deployment descriptor, they can be changed during several phases of J2EE application development: at EJB creation, at assembly (packaging), or at deployment. However, as an EJB developer, it is your responsibility to specify the attributes when creating the EJB. The attributes should be modified only when you (or whoever is assembling) are assembling components into larger applications.


Note

Do not expect the person who is deploying the J2EE application to specify the transaction attributes.


You can specify the transaction attributes for the entire enterprise bean or for individual methods. If you've specified one attribute for a method and another for the bean, the attribute for the method takes precedence.


Tip

If you're unsure about how to set up transactions in the EJB’s deployment descriptor, specify container-managed transactions. Then, set the Required transaction attribute for the entire enterprise bean. This approach will work most of the time.


For more information, on the EJB deployment descriptor file, refer to “Creating Deployment Descriptors” on page 174.

This section addresses the following topics:

Differing Attribute Requirements

When specifying attributes for individual methods, the requirements differ with the type of bean.

Attribute Values

A transaction attribute may have one of the following values:

Required

If the client is running within a transaction and invokes the enterprise bean's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method.


Tip

The Required attribute will work for most transactions. Therefore, you may want to use it as a default, at least in the early phases of development. Because transaction attributes are declarative, you can easily change them at a later time.


RequiresNew

If the client is running within a transaction and invokes the EJB's method, the container takes the following steps:

  1. Suspends the client's transaction.
  2. Starts a new transaction.
  3. Delegates the call to the method.
  4. Resumes the client's transaction after the method completes.

If the client is not associated with a transaction, the container starts a new transaction before running the method.

You should use the RequiresNew attribute when you want to ensure that the method always runs within a new transaction.

Mandatory

If the client is running within a transaction and invokes the EJB's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container throws a TransactionRequiredException.

Use the Mandatory attribute if the EJB's method must use the transaction of the client.

NotSupported

If the client is running within a transaction and invokes the EJB's method, the container suspends the client's transaction before invoking the method. After the method has completed, the container resumes the client's transaction.

If the client is not associated with a transaction, the container does not start a new transaction before running the method.

Supports

If the client is running within a transaction and invokes the EJB's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container does not start a new transaction before running the method.


Note

Because the transactional behavior of the method may vary, you should use the Supports attribute with caution.


Never

If the client is running within a transaction and invokes the enterprise bean's method, the container throws a RemoteException. If the client is not associated with a transaction, the container does not start a new transaction before running the method.

Use the NotSupported attribute for methods that don't need transactions. Because transactions involve overhead, this attribute may improve performance.

The following table summarizes the effects of the transaction attributes. Transactions can be T1, T2, or None. (Both T1 and T2 transactions are controlled by the container.)

Rolling Back a Container-Managed Transaction

There are two ways to roll back a container-managed transaction:

When the container rolls back a transaction, it always undoes the changes to data made by SQL calls within the transaction. However, only in entity beans will the container undo changes made to instance variables. (It does so by automatically invoking the entity bean's ejbLoad method, which loads the instance variables from the database.)

A session bean must explicitly reset any instance variables changed within the transaction when a rollback occurs. The easiest way to reset a session bean's instance variables is by implementing the SessionSynchronization interface.

Synchronizing a Session Bean's Instance Variables

The SessionSynchronization interface, which is optional in session beans, allows you to synchronize the instance variables with their corresponding values in the database. The container invokes the SessionSynchronization methods—afterBegin, beforeCompletion, and afterCompletion—at each of the main stages of a transaction.

Methods Not Allowed in Container-Managed Transactions

For container-managed transactions, you should not invoke any method that might interfere with the transaction boundaries set by the container. Prohibited methods are:

You may, however, use these methods to set boundaries in bean-managed transactions.


Using Bean-Managed Transactions

In a bean-managed transaction, the code in the session or message-driven bean explicitly marks the boundaries of the transaction. By moving transaction management to the bean level, you gain the ability to place all the bean’s activities—even those not directly tied to database access—under the same transaction control as your database calls. This guarantees that all application parts controlled by a bean run as part of the same transaction.

In a failure situation, either everything the bean undertakes is committed, or everything is rolled back.

The following sections are related to developing enterprise beans with bean-managed transactions:

Choosing the Type of Transactions

When coding a bean-managed transaction for session or message-driven beans, you must decide whether to use JDBC or JTA transactions.


Note

In a session bean with bean-managed transactions, it is possible to mix JDBC and JTA transactions. However, this could make your code difficult to debug and maintain.


The following sections discuss both types of transactions:

JDBC Transactions

JDBC transaction is controlled by the transaction manager of the database. You may want to use JDBC transactions when wrapping legacy code inside a session bean.

To code a JDBC transaction, you invoke the commit and rollback methods of the java.sql.Connection interface. The beginning of a transaction is implicit. A transaction begins with the first SQL statement that follows the most recent commit, rollback, or connect statement. (This rule is generally true, but may vary with database vendor.)

For additional information on JDBC, refer to the Sun Java System Application Server Developer’s Guide to J2EE Services and APIs.

JTA Transactions

JTA allows you to demarcate transactions in a manner that is independent of the transaction manager implementation. The J2EE SDK implements the transaction manager with the JTS. But your code doesn't call the JTS methods directly. Instead, it invokes the JTA methods, which then call the lower-level JTS routines.

A JTA transaction is controlled by the J2EE transaction manager. You may want to use a JTA transaction because it can span updates to multiple databases from different vendors. A particular database’s transaction manager may not work with heterogeneous databases.

The J2EE transaction manager does have one limitation—it does not support nested transactions. In other words, it cannot start a transaction for an instance until the previous transaction has ended.

For additional information on the JTA, refer to the Sun Java System Application Server Developer’s Guide to J2EE Services and APIs.

Returning Without Committing

A stateless session bean with bean-managed transactions that has begun a transaction in 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.

Methods Not Allowed in Bean-Managed Transactions

For bean-managed transactions, do not invoke the getRollbackOnly and setRollbackOnly methods of the EJBContext interface. These methods should be used only in container-managed transactions.


Note

For bean-managed transactions, invoke the getStatus and rollback methods of the UserTransaction interface.



Setting Transaction Timeouts

For container-managed transactions, you control the transaction timeout interval by setting the value of the timeout-in-seconds property in the server.xml file. For example, you would set the timeout value to 5 seconds as follows:

With this setting, if the transaction has not completed within 5 seconds, the EJB container rolls the transaction back.


Note

Only enterprise beans using container-managed transactions are affected by the timeout-in-seconds property. For enterprise beans using bean-managed JTA transactions, you invoke the setTransactionTimeout method of the UserTransaction interface.



Handling Isolation Levels

Transactions not only ensure the full completion (or rollback) of the statements that they enclose, but also isolate the data modified by the statements. The isolation level describes the degree to which data being updated is visible to other transactions.

If the transaction allows other programs to read uncommitted data, performance may improve because the other programs don't have to wait until the transaction ends. But this may also cause a problem—if the transaction subsequently rolls back, another program might read the wrong data.

For entity beans with bean-managed persistence and for all session beans, you can set the isolation level programmatically with the API provided by the underlying database. A database, for example, might allow you to permit uncommitted reads by invoking the setTransactionIsolation method.

For entity beans that use container-managed persistence, you can use the consistency element in the sun-cmp-mapping.xml file to set the isolation level.


Caution

Do not change the isolation level in the middle of a transaction. Usually, such a change causes the database software to issue an implicit commit. Because the isolation levels offered by database vendors may vary, you should check the database documentation for more information. Isolation levels are not standardized for the J2EE platform.




Previous      Contents      Index      Next     


Copyright 2004 Sun Microsystems, Inc. All rights reserved.