shashank created CAMEL-25122:
--------------------------------

             Summary: camel-sjms - InOut: when the send fails, the request 
timeout completes the exchange a second time (the reply handler is registered 
before the send and never cancelled)
                 Key: CAMEL-25122
                 URL: https://issues.apache.org/jira/browse/CAMEL-25122
             Project: Camel
          Issue Type: Bug
          Components: camel-sjms, camel-sjms2
            Reporter: shashank


{{SjmsProducer.processInOut}} registers the reply handler in the correlation 
map inside {{MessageCreator.createMessage}} 
({{replyManager.registerReply(...)}}), which runs 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, the timeout checker evicts it, and 
{{ReplyManagerSupport.processReply}} completes the same exchange a second time: 
it replaces the exception with an {{ExchangeTimedOutException}} and calls 
{{callback.done(false)}}.

This is the bug that CAMEL-24073 fixed in camel-jms (4.22.0). camel-sjms has 
the same code and was not changed; its {{ReplyManager}} has no way to cancel a 
pending reply.

Two more cases complete the exchange twice, the other way around (the same as 
CAMEL-25095 for camel-jms):
* the send blocks longer than {{requestTimeout}} and then fails: the timeout 
completes the exchange first, then the send failure completes it again;
* the request reaches the broker and is answered, and then the send reports a 
failure (a lost acknowledgement): the reply completes the exchange first, then 
the send failure.

Reproduced with a unit test in camel-sjms (embedded Artemis; the connection 
factory is wrapped so that the send to one queue fails, no Camel code changed), 
InOut to {{sjms:queue:...}}:
* the send fails at once, {{requestTimeout=500}}: the exchange fails with the 
send failure, and about 500 ms later its exception is replaced by 
{{ExchangeTimedOutException}} (the second completion).
* the send blocks until the request timeout has completed the exchange, then 
fails: the caller gets the send failure instead of the 
{{ExchangeTimedOutException}} that completed the exchange.
* the reply arrives while the send is still running, then the send fails: the 
caller gets the send failure although the reply had completed the exchange.

A second completion runs the on completions of the exchange a second time (such 
as a consumer's commit and rollback), and runs error handling on a completed 
exchange (for camel-jms, CAMEL-25095 also showed a negative inflight count; not 
measured here).

h3. Proposed fix

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.
* When the send fails, {{processInOut}} cancels the correlation id it 
registered. 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.

With the fix, the three cases above complete the exchange once, with the send 
failure, the {{ExchangeTimedOutException}} and the reply respectively. The new 
method on {{ReplyManager}} and the changed outcome of a late send failure need 
an upgrade guide note.

Affected: all versions of camel-sjms, and camel-sjms2, which uses the 
camel-sjms producer (and gets the fix too).

Duplicate check (2026-09-29): JIRA component camel-sjms since June 2025 (15 
issues: flaky tests, CAMEL-24083 asyncConsumer, CAMEL-23646, ObjectMessage and 
header filtering: nothing on this), text "sjms" with "timeout" and "twice": 
nothing. CAMEL-24073 and CAMEL-25095 are camel-jms only. GitHub pull requests 
"SjmsProducer", "sjms cancelCorrelationId": nothing on this.

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to