[
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)