Wednesday, June 24, 2009

Mixing transactions manual and container managed with JTA

How-to Mix manual transactions and container managed transactions


Container managed transactions use JTA for transaction management. If we need to mix the manual transactions and container managed transactions we have to use the JTA for the manual transactions as well.


You can use the following two classes for handling manual transactions with JTA.





Listing : Class CustomTransactionCallbackWithoutResult





public abstract class CustomTransactionCallbackWithoutResult {

   public abstract void doInTransactionWithoutResult();

}




Listing : Class CustomTransactionTemplate



import javax.transaction.UserTransaction;

import javax.transaction.SystemException;



public class CustomTransactionTemplate {

 


   
UserTransaction ut;
 


    public CustomTransactionTemplate(UserTransaction ut) {

        this.ut = ut;

   
}
    public void execute(CustomTransactionCallbackWithoutResult transactionCallbackWithoutResult) {
      

            try {
        

              try {

                ut.begin();

                transactionCallbackWithoutResult.doInTransactionWithoutResult();

                ut.commit();
            } catch (Throwable ex) {

                try {

                  ut.rollback();

                } catch (SystemException syex) {

                  throw new Exception( "Rollback failed: " + syex.getMessage());

                }

                 throw new Exception( "Transaction failed: " + ex.getMessage());

           }

        } catch (Throwable e) {

            throw new RuntimeException(e);

        }
    }





Using the above two classes

 


InitialContext ic = new InitialContext();

UserTransaction ut = (UserTransaction) c.lookup("java:comp/UserTransaction");

final DataSource ds = (DataSource) c.lookup("java:/sampleDS");

 

CustomTransactionTemplate txTemplate = new CustomTransactionTemplate(ut);

txTemplate.execute(new CustomTransactionCallbackWithoutResult() {

   public void doInTransactionWithoutResult() {

     //We are in the transaction
                        // Use ds and update a table

     // call a session bean which in turn call Entity bean

    // and cause Container  managed transactions                     

     //

     }

 });



 

When mixing container managed transactions and manual transactions if  you try to use the setAutoCommit() or Hibernate TransactionTemplate the following errors will be fired. To avoid the error the best bet is to use the JTA transactions in every place.

 


java.sql.SQLException: Connection handle has been closed and is unusable at org.jboss.resource.adapter.jdbc.WrappedConnection.checkStatus(WrappedConnection.java:537) at org.jboss.resource.adapter.jdbc.WrappedConnection.checkTransaction(WrappedConnection.java:524) at org.jboss.resource.adapter.jdbc.WrappedConnection.prepareStatement(WrappedConnection.java:184) at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:505) at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:423) at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:139) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1547) at org.hibernate.loader.Loader.doQuery(Loader.java:673) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236) at org.hibernate.loader.Loader.doList(Loader.java:2220)     


 

1 comment:

Anonymous said...

Stupid!

Post a Comment

Subscribe