How to manually commit a managed transaction

vz0 picture vz0 · Jan 25, 2011 · Viewed 13.8k times · Source

I was given an "API" in the form of a JAR to do some external accounting operations from my Java-Seam-Hibernate appplication.

Internally, the API is an plain Hibernate application, using two independent data sources besides the one used from Seam itself.

The issue is that one of the "API" operations raises the following Exception when doing an internal .commit():

java.sql.SQLException: You cannot commit during a managed transaction!
    at org.jboss.resource.adapter.jdbc.BaseWrapperManagedConnection.jdbcCommit(BaseWrapperManagedConnection.java:543)
    at org.jboss.resource.adapter.jdbc.WrappedConnection.commit(WrappedConnection.java:334)
    at org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit(JDBCTransaction.java:139)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:115)
    at com.other.APIAccountingImpl.moneyMovement(APIAccountingImpl.java:261)
    at com.myapp.integration.ExternalApiIntegrator.storeAcountingData(ExternalApiIntegrator.java:125)
    at com.myapp.session.EmployeeAccounting.persistData(EmployeeAccounting.java:123)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at ...

The source code of the moneyMovement method looks like the standard Hibernate Session transaction idiom:

Session sess = factory.openSession();
Transaction tx;
try {
    tx = sess.beginTransaction();
    //do some work
    ...
    tx.commit();
}
catch (Exception e) {
    if (tx!=null) tx.rollback();
    throw e;
}
finally {
    sess.close();
}

I'm using Seam managed transactions with JTA. I'm also forced to use the custom API and I'm not allowed to alter the source code.

What are my alternatives? How can I isolate the Seam managed transactions from the "API" Hibernate Session? It is possible to configure a connection from a specific data source to not be a managed trx?

Answer

jpkrohling picture jpkrohling · Jan 25, 2011

You are probably using JTA, which is a Java EE standard for transaction management. In this case, you are using a managed transaction. It means that the container (JBoss, it seems) is handling the transaction boundaries, and will use the JTA semantics to rollback the transaction in case you throw some exception. In this scenario, you don't deal with the transaction API directly. You just throw some exception in case something wrong happens, and it'll take care of rolling back the other parts of the transaction.

That said, I'd recommend you to confirm that this JAR you received is the JTA api. If it's not, then you'll certainly need the documentation for it. If it is, you can use the transaction API (and annotations) to use explicit demarcation of transactions. (some documentation is available here: http://download.oracle.com/javaee/5/tutorial/doc/bnciy.html#bnciz)

Overall, I would say that it's usually a good idea to let the container manage your transactions, as a transaction is usually in the context of a business method, which may involve two or more DAO calls, thus, existing beyond the transactions you'd have inside each DAO method.