EJB Transactions

EJB transactions are a set of concepts and a set of mechanisms that attempt to insure the integrity and consistency of a database for which multiple clients may attempt to access it and/or update it simultaneously.

The reader is expected to understand the rationale for and basic principles involved in transactions.  Here, the discussion will focus on second-level concepts, such as the various types of transaction included in the Java Transaction Service specification, and on specific mechanisms for specifying the transaction properties for EJB classes and methods.

Basic transactions options supported by WebSphere Studio and WebSphere, itself, are summarized.  This is followed by a brief discussion of implementation details for transactions that require two-phase commits.


ACID

Basic properties of transactions can be summarized using the ACID mnemonic:

Atomic All or nothing.  If a transaction is interrupted, all previous steps within that transaction are undone.
Consistent The state of objects and/or the state of tables within a database move from one consistent state to another consistent state.
Isolated What happens within one transaction should not affect or be visible within another transaction
Durable The effects of a transaction are persistent.

 


Transaction Attributes

Transactions can be defined at several different levels and in several different ways. 

Levels.  With respect to levels, transaction attributes may be defined at the level of EJB (or class), method within class, or segment of code within method.  The more specific specification take precedence over the specification for the containing segment.  Thus, attributes specified for a particular method take precedence over the specification for an entire EJB.

Specification.  With respect to specification, transaction attributes may be specified through deployment descriptors or through Java code embedded in a class.  Unless the programmer is skilled in working with transaction and unless there is a compelling reason to do so, a best practices approach for most applications will be to specify transactions declaratively -- through deployment descriptors attached to EJB classes that enable the EJB Container to generate and handle transactions.  Declarative transactions attributes can be set at the time of development, through WebSphere Studio, and/or at the time of deployment (or thereafter), through the WebSphere Administrative Console.  In both cases, attributes can be set for the bean as a whole, for individual methods, or both.

The EJB 2.0 Specification (see Chapter 17) includes six defined transaction attributes:

TX_REQUIRED Methods executed within a transaction.  If client provides transaction, it is used; if not, new transaction generated.  Commit at end of method.  Default attribute set by WebSphere Studio.
Well-suited for EJB Sessions.
TX_MANDATORY Client of this EJB must create a transaction in which this method operates, otherwise an error.
Well-suited for EJB Entitys.
TX_REQUIRES_NEW Methods executed within a transaction.  If client provides transaction, it is suspended.  A new transaction is generated, regardless.  Commit at end of method.
TX_SUPPORTS Transactions optional.
TX_NOT_SUPPORTED Transactions not supported; if provided, ignored..
TX_BEAN_MANAGED Code in the EJB responsible for explicit transaction control.  Applicable in WebSphere to EJB Sessions only.

Consider:  what aspects of the ACID mnemonic are covered/not covered by transaction attributes?

 


Isolation Levels

Isolation levels provide a degree of control of the effects one transaction can have on another.  Since concurrent effects are determined by the precise ways a DBMS handles locks, and databases and their drivers handle these locks differently, the semantics of isolation mechanisms based on them are not well-defined.  Nevertheless, certain defined or approximate properties can be specified.

TRANSACTION_SERIALIZABLE Strongest level of isolation.  All rows locked for duration of transaction. Can produce deadlocks! (But not if Find for Update set to false.)
TRANSACTION_REPEATABLE_READ Transaction always reads same data during transaction. Phantom records possible. Default level of isolation set by WebSphere Studio.  Usually suitable for all but most critical operations.
TRANSACTION_READ_COMMITTED Can't read uncommitted data by another transaction, but nonrepeatable reads and phantom records possible.
TRANSACTION_READ_UNCOMMITTED Can read uncommitted data by another transaction, and nonrepeatable reads and phantom records possible.

 


Implementing Two-Phase Commits

Operations that involve two different EJBs present special problems for transaction processing.  For example, an update to the first EJB may be successful, but the update to the second one may fail.  To ensure that the database is left in a consistent state, the update to the first EJB, and hence its corresponding table in the DB, must be undone, or rolled back.

Roll back is an operation that requires a special form of transaction support, called two-phase commit.  See the discussion In Kyle Brown's book (Chapter 28) for a general discussion of transactions in WebSphere.  See, also, Don Smith's presentation on transactions and André Risnes' conceptual discussion of the two-phase commit protocol.  Transactions that are managed by the container are defined with respect to the thread in which the operations that are to be subjected to two-phase commit take place.  Thus, if the architecture includes a Session EJB in which a method calls a domain object that, in turn, carries out operations on several entity EJBs that are to be treated as an atomic unit, then the transaction should be defined in the Session EJB method.

A checklist of key steps for specifying this follows:.

  1. In the Session EJB method, enclose the statement(s) that start the thread that eventually reaches the operations on multiple EJBs within a try-catch block; e.g.,
    try  {
    	return domain.updateBoth( DataBean dataBean);
    }  catch ( Exception e )  {
    	mySessionCtx.setRollbackOnly();
    }
    Note: mySessionCtx  is a global variable that is generated by WSAD and included in the Session EJB.
  2. In the Server Perspective, select or create the particular server in which you wish to carry out two-phase commit and open its deployment descriptor (.wsi file).  Select the DataSource tab and under Server Settings, go to the JDBC Prover List.  There, designate ADD and select IBM DB2 as the Database Type and DB2 JDBC Provider (XA) as the Provider type.  Note:  XA is the designation for two-phase commit resources.  When prompted, give the new two-phase resource a name.
  3. Select the newly created resource and add a new DataSource, in the next panel down.  the process is similar to that done before for Entity EJBs.  If you are adding two-phase commit late in the process after you have defined a server with single-phase commit, you may wish to use the same JNDI name so that you don't have to change the JNDI name on individual EJBs.