Claus Ibsen created CAMEL-26184:
-----------------------------------

             Summary: camel-quickfix - an InOut consumer replies to every 
event, re-sending the Logon until StackOverflowError, and an InOut producer 
without CorrelationCriteria always times out
                 Key: CAMEL-26184
                 URL: https://issues.apache.org/jira/browse/CAMEL-26184
             Project: Camel
          Issue Type: Bug
          Components: camel-quickfix
            Reporter: Claus Ibsen
             Fix For: 4.24.0


Found while adding the catalog body types of quickfix (CAMEL-24961, PR #28413).

h4. 1. An InOut consumer replies to every event, and re-sends the Logon 
recursively

{{QuickfixjConsumer.onExchange}} (main 2a465aa4814c, line 65 to 66) sends the 
message body back as a reply for every exchange that is out capable and has an 
out message, whatever the event category. Messages the route does not answer 
are echoed back to the counterparty. For the {{AdminMessageSent}} event of the 
Logon, {{sendOutMessage}} (line 74) sends the Logon again, which raises a new 
{{AdminMessageSent}} event, and so on until a StackOverflowError. The InOut 
consumer example in the component doc runs into this. Checked on 
4.24.0-SNAPSHOT with an in-process VM_PIPE acceptor and initiator and an InOut 
consumer route.

Proposed: reply only to application messages received ({{AppMessageReceived}}), 
and only when the route set a reply.

h4. 2. An InOut consumer reply that cannot be converted fails inside fromApp, 
and the engine loops on ResendRequests

{{QuickfixjConsumer.sendOutMessage}} (line 76) reads the reply with the 
non-mandatory {{getBody(quickfix.Message.class)}}. A Map or null reply becomes 
null and {{Session.send(null)}} (line 85) throws a NullPointerException inside 
the QuickFIX/J {{fromApp}} callback: the incoming sequence number is not 
advanced, the counterparty gets ResendRequests forever and the route runs again 
for each resend. Checked on 4.24.0-SNAPSHOT with the in-process acceptor and 
initiator, a consumer route that sets a Map body.

Proposed: convert with {{getMandatoryBody}}, and send no reply (log or hand the 
error to the exception handler) when the reply is not a FIX message, so the 
callback completes.

h4. 3. An InOut producer without CorrelationCriteria never gets a reply, and 
every engine event fails meanwhile

{{MessageCorrelator.getReply}} (line 36 to 38) adds a correlation rule even 
when the exchange has no {{CorrelationCriteria}} property (the doc lists "None" 
as its default), so the rule has a null predicate. 
{{MessageCorrelator.onEvent}} (line 59) then calls 
{{rule.getMessageCriteria().evaluate(message)}} for every engine event and 
throws a NullPointerException, and the exchange times out. PR #28378 
(CAMEL-25855) now removes the rule after the timeout, but a request without 
criteria still cannot get a reply. Checked on 4.24.0-SNAPSHOT with the 
in-process acceptor and initiator, an InOut producer without the property.

Proposed: fail fast with a clear error when an InOut exchange has no 
CorrelationCriteria (or treat it as InOnly), and skip rules with a null 
predicate in onEvent.

h4. 4. A producer body that does not convert to a FIX message fails with a bare 
NPE

{{QuickfixjProducer.sendMessage}} (line 69) uses the non-mandatory 
{{getBody(Message.class)}}; for a stream, a Map or a null body the message is 
null and the exchange fails with the NullPointerException "message is null" 
from {{MessageUtils.getSessionID}} (line 74). Checked on 4.24.0-SNAPSHOT with 
the in-process acceptor and initiator.

Proposed: use {{getMandatoryBody(Message.class)}} so the error names the body 
type that could not be converted.

_Claude Code on behalf of davsclaus_



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to