Tuesday, March 20, 2012

JTA and Transaction Attributes

JTA and Transaction Attributes

Dear reader,
In this blog article I have discussed about JTA (Java Transaction API) and Transaction Attributes.

The Contents are taken from below site but edited for my reading purpose:
http://www.java-tips.org/java-ee-tips/enterprise-java-beans/introduction-to-the-java-transactio.html

A transaction is a series of operations that must be performed atomically. In other words, each operation 
in the transaction series must succeed for the entire transaction to be successful. If any operation in the 
transaction does not succeed, the entire transaction fails. At that point, any operations which have succeeded 
must be "rolled back" so that the end state matches with what was in place when the transaction started.

For example, let's say you want to transfer $50 from a savings account (account number: 12345-1) to a checking 
account (account number 12345-2). The steps in this transaction can be stated in "pseudo code" as follows:

   BOUNDARY: START TRANSACTION A
   SUBTRACT 50 DOLLARS FROM SAVINGS ACCOUNT 12345-1
   ADD 50 DOLLARS TO THE CHECKING ACCOUNT 12345-2
   BOUNDARY: END TRANSACTION A

To run the transaction, the following code is required:
   PREPARE (RUN) TRANSACTION A
   IF TRANSACTION A SUCCEEDED
       COMMIT TRANSACTION A
   ELSE
       ROLLBACK TRANSACTION A

Let's assume that there are sufficient funds to subtract $50 from the savings account, so the first part of 
the transaction succeeds. However, let's also assume that the second part fails. When the computer attempts 
to add 50 dollars to the checking account, it discovers that the checking account is frozen. Because the 
second part of the transaction fails, the entire transaction fails. As a result, the first part of the transaction 
needs to be rolled back: means $50 needs to be placed back into the savings account 12345-1. This is essential. 
Otherwise, each time the computer tries to transfer money from the savings to the checking account, it will 
lose the money!

If the entire transaction succeeds, then the entire transaction is committed, and the results are made permanent.

Note that the commit process takes two phases to complete. In the first phase, checks are made to see that the 
transaction ran without error. If there were no errors, the results are committed in the second phase. If there 
were errors in the first-phase check, the transaction is rolled back. This common transaction strategy is 
appropriately called the two-phase commit protocol.

Transactions in the J2EE Environment:
    The Java Transaction API(JTA) is part of the J2EE platform. The API gives you the ability to perform 
    distributed transactions, that is, an application can use the API to perform transactions on more than 
    one data store in the network at the same time. But to do this efficiently, it helps to have another 
    component operating in the application server: a J2EE transaction manager. A transaction manager helps 
    to efficiently schedule and execute the potentially large number of transactions coming in through the 
    application server.

Many database vendors provide their own transaction managers. However, a particular DBMS's transaction 
manager might not work with databases from different vendors. If you want to work with these heterogeneous 
databases, for example, if you want to update multiple databases from different vendors, you should consider 
using a JTA transaction with a corresponding J2EE transaction manager. The JTA specification states that 
"A JTA transaction is controlled by the J2EE transaction manager." Note that the J2EE transaction manager 
does have one limitation: the J2EE transaction model is flat. Support for nested transactions is not part 
of J2EE. This means that the J2EE transaction manager cannot start a transaction for an instance until the 
previous transaction has ended.

Learning the JTA:
There are three separate interfaces that you can use with the JTA to perform transactions, and each uses a 
unique approach to handling transactions. The interfaces are:

    javax.transaction.UserTransaction: This interface allows you to specify the transaction boundaries, 
        bypassing a transaction manager.

    javax.transaction.TransactionManager. This interface allows you to delegate the boundaries of the 
        transactions, as well as various transaction operations, to the J2EE transaction manager.

    javax.transaction.xa.XAResource. This interface maps to the X/Open CAE Specification (Distributed Transaction 
        Processing: The XA Specification) standard for using third-party XA-compliant transaction managers to perform 
        transactions.

Because most J2EE programmers only use the first interface, I am writing for that only.

EJB Transactions: Container and Bean-Managed Transactions, not explaining here.

Container-managed transactions can be used with any type of enterprise bean (session bean, entity bean, or message-
driven bean). With container-managed transactions, the EJB container sets the boundaries of the transaction. This is 
typically done by marking one or more methods in the bean as individual transactions. The container sets the 
transaction boundary just before the beginning of the method, and sets the end boundary just before the method 
exits. However, with container-managed transactions, each method can be only one transaction -- multiple transactions 
are not allowed. When deploying a bean, you specify which of the bean's methods are associated with transactions. 
You do this by setting the transaction attributes.

The sequence of transaction events differs between container-managed and bean-managed transactions.
Below are the sequence:

Container-managed Transactions:
For EJB applications with container-managed transactions, a basic transaction works in the following way:

1.  In the EJB’s deployment descriptor, the Bean Provider or Application Assembler specifies the transaction type 
    (transaction-type element) for container-managed demarcation (Container).
   
2.  In the EJB’s deployment descriptor, the Bean Provider or Application Assembler specifies the default transaction 
    attribute (trans-attribute element) for the EJB, which is one of the following settings: 
    NotSupported, Required, Supports, RequiresNew, Mandatory, or Never. 
    Detailed description of all these attributes are written in the blog article.
 
3.  However in the EJB’s deployment descriptor, we can set trans-attribute for one or more methods as per 
    requirement. However this is optional.
4.  When a client application invokes a method in the EJB, the EJB container checks the trans-attribute setting in the 
    deployment descriptor for that method. If no setting is specified for the method, the EJB uses the default 
 trans-attribute setting for that EJB.
 
5.  The EJB container takes the appropriate action depending on the applicable trans-attribute setting.
        For example, if the trans-attribute setting is Required, the EJB container invokes the method within the 
    existing transaction context or, if the client called without a transaction context, the EJB container 
    begins a new transaction before executing the method.
  
        In another example, if the trans-attribute setting is Mandatory, the EJB container invokes the method within 
    the existing transaction context. If the client called without a transaction context, the EJB container throws 
    the javax.transaction.TransactionRequiredException exception.
  Detailed description of all these attributes are written in the blog article.
 
6.  During invocation of the business method, if it is determined that a rollback is required, the business method 
    calls the EJBContext.setRollbackOnly method, which notifies the EJB container that the transaction is to be 
 rolled back at the end of the method invocation.
    Note: Calling the EJBContext.setRollbackOnly method is allowed only for methods that have a meaningful transaction 
 context.
 
7. At the end of the method execution and before the result is sent to the client, the EJB container completes the 
   transaction, either by committing the transaction or rolling it back (if the EJBContext.setRollbackOnly() was called).



Bean-managed Transactions:
For EJB applications with bean-managed transaction demarcations, a basic transaction works in the following way:

1.  In the EJB’s deployment descriptor, the Bean Provider or Application Assembler specifies the transaction type 
    (transaction-type element) for container-managed demarcation (Bean).
2.  The client application uses JNDI to obtain an object reference to the UserTransaction object for the WebLogic 
    Server domain.
    
3.  The client application begins a transaction using the UserTransaction.begin method, and issues a request to 
    the EJB through the EJB container. All operations on the EJB execute within the scope of a transaction.
        If a call to any of these operations raises an exception (either explicitly or as a result of a communication 
  failure), the exception can be caught and the transaction can be rolled back using the UserTransaction.rollback 
  method.
        
  If no exceptions occur, the client application commits the current transaction using the UserTransaction.commit 
  method. This method ends the transaction and starts the processing of the operation. The transaction is committed 
  only if all of the participants in the transaction agree to commit.
  
4.  The UserTransaction.commit method causes the EJB container to call the transaction manager to complete the transaction.
5.  The transaction manager is responsible for coordinating with the resource managers to update any databases.



Transaction attributes control the scope of a transaction when one enterprise bean method calls another enterprise 
bean method. The JTA specification states that an enterprise bean method can be marked with one of six different 
transaction attributes in the EJB deployment descriptor. The transaction attribute indicates how the EJB container 
should treat the method called by the client enterprise bean when transactions are involved.

Transaction attributes appear in the EJB deployment descriptor as follows:
   <ejb-jar>
     ...
    <enterprise-beans>
    ... 
     </enterprise-beans>
     <assembly-descriptor>
       <container-transaction>
         <method>
           <ejb-name>BankBean</ejb-name>
           <method-intf>Remote</method-intf>
           <method-name>transferMoney</method-name>
           <method-params>
             <method-param>java.lang.String</method-param>             
             <method-param>java.lang.double</method-param>
           </method-params>
         </method>
         <trans-attribute>Required</trans-attribute>
       </container-transaction>
     </assembly-descriptor>
   </ejb-jar>

Here is what the specification says about each of the six transaction attributes:

    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. Most container-managed 
        transactions use Required.

    RequiresNew - If the client is running within a transaction and invokes the enterprise bean's method, 
        the container suspends the client's transaction, starts a new transaction, delegates the call to the 
        method, and finally 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.

    Mandatory - 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 throws the TransactionRequiredException. Use the Mandatory attribute if the enterprise 
        bean's method must use the transaction of the client.

    NotSupported - If the client is running within a transaction and invokes the enterprise bean'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. Use the NotSupported attribute 
        for methods that don't need transactions. Because transactions involve overhead, this attribute may 
        improve performance.

    Supports - 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 
        does not start a new transaction before running the method. 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.

There are two ways to Roll-back a container-managed transaction. If a system exception is thrown, the container 
automatically rolls back the transaction. You can also roll back a transaction by invoking the setRollbackOnly() 
ethod of the EJBContext interface. This instructs the container to roll back the transaction. If an enterprise bean 
throws an application exception, the rollback is not automatic, but the rollback can be initiated by a call to 
setRollbackOnly(). Note that you cannot invoke some JTA methods while using container-managed transactions. 
That's because these methods are reserved for use with bean-managed transactions. These methods are:

    Any resource-specific functions that conflict with the transactional semantics, such as the commit(), 
    setAutoCommit(), and rollback() methods of java.sql.Connection.
    
    The getUserTransaction() method of javax.ejb.EJBContext.
    
    Any method of javax.transaction.UserTransaction

In a bean-managed transaction, the code explicitly marks the boundaries of the transaction. 
When you code a bean-managed transaction you typically can use either JDBC or JTA transactions. 
A JDBC transaction is controlled by the transaction manager of the database management system, and 
not by the J2EE transaction manager. To perform a JDBC transaction, use the commit() and rollback() methods of the 
java.sql.Connection interface. 

The beginning of a transaction is generally assumed with the first SQL statement that follows the most recent commit(), 
rollback(), or connect() statement. 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:

//All class imports
  import javax.naming.*;
  import javax.transaction.UserTransaction;
  import javax.transaction.SystemException;
  import javax.transaction.HeuristicMixedException
  import javax.transaction.HeuristicRollbackException
  import javax.transaction.NotSupportedException
  import javax.transaction.RollbackException
  import javax.transaction.IllegalStateException
  import javax.transaction.SecurityException
  import java.sql.*;
  import java.util.*;

  //Getting UserTransaction
  Context ctx = null;
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
 
  //Substitute the correct hostname, port number. Also user name, and password for your environment:
  env.put(Context.PROVIDER_URL, "t3://localhost:7001"); 
  env.put(Context.SECURITY_PRINCIPAL, "Fred");
  env.put(Context.SECURITY_CREDENTIALS, "secret");
 
  ctx = new InitialContext(env);

  UserTransaction tx = (UserTransaction) ctx.lookup("java:comp/env/jdbc/customer");
  //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());
  }   

  //Or you can get a JDBC data source connection:
  Context context=new InitialContext();
  //Set context attributes
  DataSource ds=(DataSource)context.lookup("java:comp/env/jdbc/customer");
  Connection connection=ds.getConnection();
  //Now use normal JDBC operations.


The code to perform a JDBC bean-managed transaction is similar. Note, however, that the code turns off the 
auto-commit on the database connection. This way, the database treats all subsequent operations as a single 
transaction (until the code calls the commit() method) .

   try {            
        Connection con = makeDatabaseConnection(); //Using JDBC
        con.setAutoCommit(false);           
        //  Do whatever database transaction functionality
        //  is necessary           
        con.commit();          
    } 
    catch (Exception ex) {
        try {
            con.rollback();
        } catch (SQLException sqx) {
            throw new EJBException("Rollback failed: " +
                sqx.getMessage());
        }
    } 
    finally {
        releaseDatabaseConnection();
    }

Here are a few rules stated by the JTA specification:
    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. 
    
    In a stateful session bean with a JDBC transaction, the JDBC connection retains the association between 
    the bean instance and the transaction across multiple calls. If the connection is closed, the association 
    is not retained. 

There is one method limitation with JTA 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). 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.
------------------------------END------------------------------------

No comments:

Post a Comment