allthingssecurity opened a new pull request, #27031: URL: https://github.com/apache/camel/pull/27031
# Description [CAMEL-25122](https://issues.apache.org/jira/browse/CAMEL-25122) camel-sjms still has the bug that CAMEL-24073 fixed in camel-jms: when the send of an InOut message fails, the request timeout completes the exchange a second time. `SjmsProducer.processInOut` registers the reply handler in the correlation map inside `MessageCreator.createMessage`, before the message is sent. When the send fails, the producer sets the exception and calls `callback.done(true)`, but the handler stays registered. When the request timeout expires, `ReplyManagerSupport.processReply` completes the same exchange again: it replaces the exception with an `ExchangeTimedOutException` and calls `callback.done(false)`. The sjms `ReplyManager` has no way to cancel a pending reply. The other way around is also possible, as in CAMEL-25095 for camel-jms: a send that blocks longer than `requestTimeout` and then fails (the timeout completes the exchange first), or a request that is delivered and answered before the send reports a failure (the reply completes it first). In both cases the send failure then completes the exchange a second time. This change, as in camel-jms: - `ReplyManager` gets `boolean cancelCorrelationId(String correlationId)`, implemented by `ReplyManagerSupport`: it removes the pending reply and returns whether it was still pending. - `processInOut` keeps the correlation id that `registerReply` returned. When the send fails, it cancels it. If it was still pending, the exchange fails with the send failure as before, and the timeout no longer fires. If the request timeout or the reply has already removed it, they complete the exchange, so the send failure is only logged at WARN and `processInOut` returns without completing the exchange. A failure before the reply was registered fails the exchange as before. - Upgrade guide note for 4.23: the outcome of a late send failure, and the new `ReplyManager` method (a custom `ReplyManager` has to implement it). camel-sjms2 uses the camel-sjms producer and gets the fix too. Tests: - New `InOutSendFailureCallbackTest` (camel-sjms, embedded Artemis). The connection factory is wrapped in dynamic proxies so that `MessageProducer.send()` to a given queue fails; no Camel code is changed for the test. `requestTimeoutCheckerInterval=50`. Each test counts the on completions of the exchange and checks the inflight count is 0 at the end. - The send fails at once (`requestTimeout=500`): the exchange fails with the send failure, which stays unchanged for 1.5 s, and the on completion runs `onFailure` once. - The send blocks until the request timeout (100 ms) has completed the exchange, then fails: the exchange fails with the `ExchangeTimedOutException`, `onFailure` once. - The request is sent and answered, then the send fails: the exchange has the reply, `onComplete` once. - Without the change, all 3 fail: the first one's exception is replaced by `ExchangeTimedOutException` after 500 ms, and the other two return the send failure instead of the timeout or the reply that completed the exchange. - With the change: camel-sjms, all tests: 126 tests, 0 failures, 0 errors, 5 skipped. This merges cleanly with main. Found in a review of CAMEL-25095 (camel-jms), which noted that camel-sjms has the code from before CAMEL-24073. I confirmed it with the test above before changing anything. # 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). # 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 and tested the affected modules, including the formatter and import-sort plugins. 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]
