allthingssecurity opened a new pull request, #29404: URL: https://github.com/apache/camel/pull/29404
# Description [CAMEL-26707](https://issues.apache.org/jira/browse/CAMEL-26707) `markRollbackOnly()` and `markRollbackOnlyLast()` mark the exchange for rollback without an exception, so the unit of work runs the on completions as successful (`isFailed()` only checks the exception). `IdempotentOnCompletion.onComplete` then confirmed the message id (or added it, with `eager=false`) and `removeOnFailure` had no effect; `completionEager` calls the same `onComplete`. A consumer that does not commit a rollback only exchange (such as the SQL consumer, which skips `onConsume`, or a transacted JMS consumer) redelivers the message. The Idempotent Consumer then found the message id and dropped the redelivery as a duplicate (only logged at DEBUG), and the consumer committed it: the message was never processed. This happens with the default options, with any repository that is not enlisted in the transaction that is rolled back. The SQL consumer already treats a rollback only exchange as failed: `SqlConsumer` ("a rollback only exchange (without an exception) did not complete successfully either; markRollbackOnlyLast reaches the consumer as the last transaction when no transacted() EIP consumed the flag, so honor it too", CAMEL-25527 / CAMEL-25588), and `PipelineHelper.continueProcessing` checks `isRollbackOnly() || isRollbackOnlyLast()`. Change: `IdempotentOnCompletion.onComplete` handles an exchange with `isRollbackOnly()` or `isRollbackOnlyLast()` as failed (`onFailedMessage`), as it already does for an exchange handled by a dead letter channel. An exception still goes to `onFailure`, and `removeOnFailure=false` still keeps the message id. The `IdempotentConsumerCallback` of `completionEager` goes through `onComplete` too, so it needs no change. `markRollbackOnlyLast` and `transacted()`: the transaction error handler clears the flag when it rolls back the transaction of the block, so when the unit of work is done the exchange is not rollback only any more, and the message id is kept as before (in a route with a single `transacted()`, the redelivery is still dropped as before; this change does not address that). With `completionEager=true` inside that block, the eager callback runs before the flag is cleared, so the message id is removed although an outer transaction commits; the work protected by that block was rolled back, and a repository enlisted in it loses the message id with the rollback anyway. With a consumer that commits a rollback only exchange anyway, such as the file consumer, the visible change is that a later message with the same id is processed instead of dropped as a duplicate. The upgrade guide says so. Behaviour change, so there is an entry in the 4.24 upgrade guide (the way back is `removeOnFailure=false`). Tests: `IdempotentConsumerRollbackOnlyTest` (memory repository, no database), five tests: `markRollbackOnly()`, `markRollbackOnlyLast()`, `completionEager(true)` and `eager(false)` each remove (or do not add) the message id, and the redelivered message is processed; the control with `removeOnFailure(false)` keeps the message id and the redelivery is a duplicate, as for a failed exchange. On main 4 of the 5 tests fail (the message id stays, so the redelivery is dropped); the `removeOnFailure(false)` control passes on both. With the fix 5/5, and 100/100 over 20 runs. camel-core Idempotent Consumer, rollback (`MarkRollbackOnlyTest` etc.), file idempotent and aggregator tests: 392 run (offline, together with the other camel-core change of this batch, which touches different files), 0 failures; the camel-management idempotent tests (`ManagedMemoryIdempotent*`, `ManagedFileIdempotent*`) pass. # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it): [CAMEL-26707](https://issues.apache.org/jira/browse/CAMEL-26707). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built the core modules with the formatter and import-sort plugins and ran the related camel-core tests; no generated file changes. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
