[ 
https://issues.apache.org/jira/browse/CAMEL-25698?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on CAMEL-25698 started by shashank.
----------------------------------------
> camel-jta - markRollbackOnlyLast() in a transacted() route commits the 
> transaction instead of rolling it back
> -------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25698
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25698
>             Project: Camel
>          Issue Type: Bug
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> In a {{transacted()}} route that runs with a JTA transaction manager, the 
> transaction error handler of camel-jta 
> ({{org.apache.camel.jta.TransactionErrorHandler}}) decides after routing 
> whether the transaction is rolled back. At main 7d31f3b0d8c7 
> ({{doInTransactionTemplate}}, line 215) it rolls back only when
> {code:java}
> exchange.getException() != null || exchange.isRollbackOnly()
> {code}
> {{markRollbackOnlyLast()}} sets only the rollback-only-last flag 
> ({{RollbackProcessor}}: {{exchange.setRollbackOnlyLast(true)}}, no 
> exception), and {{Exchange.isRollbackOnly()}} has returned only the 
> rollback-only flag since Camel 3. So the transaction policy sees a normal 
> return and commits. Afterwards {{processInTransaction}} clears the flag (and 
> the exception) as it should for rollback only last, so nothing on the 
> exchange shows that the rollback was skipped. The database changes and the 
> messages sent inside the transaction are committed, although the route asked 
> for them to be rolled back.
> CAMEL-17105 fixed exactly this in the camel-spring 
> {{TransactionErrorHandler}} (its condition is {{exchange.getException() != 
> null || exchange.isRollbackOnly() || exchange.isRollbackOnlyLast()}}, line 
> 224 on main); the camel-jta copy of the class was not changed. CAMEL-25588 
> (merged on 2026-10-15) makes the SQL, MyBatis and jOOQ consumers honor 
> rollback only last, on the stated assumption that a {{transacted()}} block 
> has consumed the flag; with camel-jta it consumes the flag without rolling 
> back.
> Trigger: any {{transacted()}} route with a JTA transaction manager (camel-jta 
> on the classpath) that calls {{markRollbackOnlyLast()}}, the use its javadoc 
> describes: nested transactions where only the last (inner) transaction is 
> rolled back and the outer one still completes. {{markRollbackOnly()}} and 
> exceptions are not affected.
> h3. Reproduction
> New {{TransactionErrorHandlerRollbackOnlyLastTest}} in camel-jta: a 
> {{TransactionErrorHandler}} with a {{JtaTransactionPolicy}} that records 
> whether its {{Runnable}} returned (commit) or threw (rollback), once around a 
> processor that calls {{exchange.setRollbackOnlyLast(true)}} (what 
> {{markRollbackOnlyLast()}} does), and once as a route 
> {{from("direct:start").transacted("recordingPolicy").setBody(constant("done")).markRollbackOnlyLast()}}.
>  On main the policy commits in both ({{The transaction should be rolled back 
> ==> expected: <1> but was: <0>}}).
> h3. Proposed fix
> Add {{exchange.isRollbackOnlyLast()}} to the rollback condition, as in 
> camel-spring. The flag and the exception are still cleared after the 
> transaction, so an outer {{transacted()}} block does not see them. Upgrade 
> guide 4.24: a short note, as routes that used {{markRollbackOnlyLast()}} with 
> JTA now roll back.
> camel-jta unit tests with the fix: 7 run, 0 failures, 0 skipped. Not run: the 
> module's integration test (it needs PostgreSQL), a real JTA transaction 
> manager.
> How it was found: reviewing the rollback-only changes merged this week 
> (CAMEL-25550, CAMEL-25588) and the transaction error handlers they rely on; 
> the camel-spring and camel-jta copies differ in this condition. A small probe 
> and the new test confirmed it.
> Not changed: other consumers that commit on their own (camel-jms and 
> camel-sjms with {{transacted=true}}, camel-spring-rabbitmq, camel-nats, the 
> camel-kafka transaction synchronization) check {{isRollbackOnly()}} but not 
> {{isRollbackOnlyLast()}}; whether they should follow CAMEL-25588 is a 
> separate question.
> Affected: main (7d31f3b0d8c7; tested). camel-4.23.x (line 215), camel-4.22.x 
> (line 213), camel-4.18.x and camel-4.14.x (line 201) have the same condition 
> (read, not run).
> Duplicate check (2026-10-16): JIRA text "rollbackOnlyLast", 
> "markRollbackOnlyLast", "rollback only last" (CAMEL-17105 camel-spring only, 
> CAMEL-25588, CAMEL-25550, CAMEL-3371, CAMEL-3373), "camel-jta" with 
> "rollback" (CAMEL-25504, CAMEL-23234 shutdown, CAMEL-17443 markRollbackOnly 
> does not abort), "JtaTransactionPolicy"; GitHub pull requests "CAMEL-17105" 
> (#6300, camel-spring only), "TransactionErrorHandler jta", "rollbackOnlyLast 
> jta": nothing about the camel-jta condition.
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to