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)