[jboss-jira] [JBoss JIRA] Created: (JBRULES-2937) JtaTransactionManager should use setRollbackOnly instead of rollback for non-local transactions

Vlastimil Menčík (JIRA) jira-events at lists.jboss.org
Fri Apr 1 07:38:37 EDT 2011


JtaTransactionManager should use setRollbackOnly instead of rollback for non-local transactions
-----------------------------------------------------------------------------------------------

                 Key: JBRULES-2937
                 URL: https://issues.jboss.org/browse/JBRULES-2937
             Project: Drools
          Issue Type: Bug
      Security Level: Public (Everyone can see)
    Affects Versions: 5.2.0.M1
         Environment: WinXP, Oracle Java 1.6.0_20, 32bit, JBoss AS 6.0.0.Final, jBPM 5.0.0
            Reporter: Vlastimil Menčík
            Assignee: Mark Proctor


This problem concerns the {{drools-persistence-jpa}} module and its {{org.drools.persistence.jta.JtaTransactionManager}}.

The {{JtaTransactionManager}} has a notion of local transactions. These are the JTA transactions that it itself started using [UserTransaction.begin()|http://download.oracle.com/javaee/6/api/javax/transaction/UserTransaction.html#begin%28%29].
If a JTA transaction is already active when {{JtaTransactionManager.begin()}} is called, then the execution continues in this JTA transaction and a new one is not started. Let's call such JTA transaction non-local.

The problem is that {{JtaTransactionManager.rollback()}} treats local and non-local JTA transactions the same way and calls [UserTransaction.rollback()|http://download.oracle.com/javaee/6/api/javax/transaction/UserTransaction.html#rollback%28%29] in both cases. In case of a non-local transaction is this behaviour IMHO wrong, because the rollback should be a responsibility of the same client that started the JTA transaction.

Imagine the following situation (jBPM process execution):
{code}
StatefulKnowledgeSession session = ...
UserTransaction ut = ...
ut.begin();
try {
    session.startProcess("my.process"); // the process execution may cause an exception (most likely in some WorkItemHandler)
    ut.commit();
} catch (Exception e) {
    ut.rollback(); // now this throws an IllegalStateException, because JtaTransactionManager already rolled back the transaction
}
{code}

There is of course a workaround: the client code has to check [status|http://download.oracle.com/javaee/6/api/javax/transaction/UserTransaction.html#getStatus%28%29] of the JTA transaction and must not call {{rollback()}}, if the transaction was already rolled back by the {{JtaTransactionManager}}.

IMHO the relevant JtaTransactionManager code should call [UserTransaction.setRollbackOnly|http://download.oracle.com/javaee/6/api/javax/transaction/UserTransaction.html#setRollbackOnly%28%29] for non-local transactions:
{code}
public void rollback() {
    boolean wasLocal = localTransaction; // localTransaction is a private boolean field of JtaTransactionManager already present in current implementation
    localTransaction = false;
    try {
        wasLocal ? this.ut.rollback() : this.ut.setRollbackOnly();
    } catch ( Exception e ) {
        logger.warn( "Unable to rollback transaction", e);
        throw new RuntimeException( "Unable to rollback transaction", e );
    }
} 
{code}




--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira



More information about the jboss-jira mailing list