[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