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)