[ 
https://issues.apache.org/jira/browse/CAMEL-25291?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen resolved CAMEL-25291.
---------------------------------
    Resolution: Fixed

Fixed via https://github.com/apache/camel/pull/27327

> camel-plc4x - a write that cannot be done completes the exchange 
> successfully, and the polling consumer answers a failed read with an empty 
> result
> --------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25291
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25291
>             Project: Camel
>          Issue Type: Bug
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>             Fix For: 4.23.0
>
>
> h3. 1. Producer: failed reconnect reported as success, message removed on 
> failure
> With {{autoReconnect=true}}, {{Plc4XProducer.process}} catches the 
> {{PlcConnectionException}} of a failed reconnect and returns:
> {code:java}
> } catch (PlcConnectionException e) {
>     log.warn("Unable to reconnect, skipping request");
>     return;
> }
> {code}
> The exchange completes successfully although nothing was written to the PLC: 
> the error handler, redeliveries and a dead letter channel never see the 
> failure, and the values are silently lost (the PLC is down, the network is 
> interrupted).
> When a write does fail (exception from the write future), the asynchronous 
> {{process}} does {{exchange.setMessage(null)}} before setting the exception, 
> so the message is replaced by an empty one: a redelivery then fails with "The 
> body must contain a Map", and a dead letter channel gets no body.
> h3. 2. Polling consumer: failures answered with an empty Map
> {{Plc4XPollingConsumer.doReceive}} (used by {{pollEnrich}}) catches 
> {{ExecutionException}}, {{TimeoutException}} and {{PlcConnectionException}} 
> and returns an exchange whose body is an empty {{HashMap}} and that has no 
> exception. The route cannot tell a failed read from a read, and goes on with 
> no values. A read that does not answer within the timeout is answered the 
> same way; with {{receiveNoWait()}} ({{pollEnrich}} with timeout 0) this is 
> nearly always the case, since {{future.get(0, ms)}} times out unless the 
> response is already there. The {{PollingConsumer}} contract is to return 
> {{null}} when nothing is received within the timeout.
> h3. Reproduction
> {{Plc4XFailureTest}} (new, mocked {{Plc4XEndpoint}}):
> * {{testProducerFailsWhenReconnectFails}}: on main the exchange has no 
> exception.
> * {{testProducerKeepsTheMessageWhenTheWriteFails}}: on main the body is 
> {{null}} after the failed write.
> * {{testPollingConsumerFailsWhenReconnectFails}}, 
> {{testPollingConsumerFailsWhenReadFails}}: on main no exception (body {{{}}}).
> * {{testPollingConsumerReturnsNullWithoutResponse}}: on main an exchange with 
> an empty Map instead of {{null}}.
> * {{testPollingConsumerReadsTags}}: control, passes on main.
> h3. Proposed fix
> * Producer: let the reconnect failure fail the exchange; do not remove the 
> message on failure.
> * Polling consumer: set the exception of a failed connection or read on the 
> returned exchange ({{pollEnrich}} copies it to the exchange), return {{null}} 
> when the read does not answer within the timeout, keep the interrupt status 
> when interrupted.
> History: the "skipping request" of the producer came with the 
> {{autoReconnect}} option (2023, PR #8971) without a stated reason; the review 
> only asked to log it at WARN, in the event-driven consumer, where skipping a 
> read is harmless. The empty Map of the polling consumer was a choice of 
> CAMEL-18861 (PR #9254, commit note: "An exchange with an empty map is created 
> when no connection could be made" (instead of no exchange)). The fix keeps 
> returning an exchange for a failed connection or read, but with the 
> exception, so that the route sees the failure; only a read without an answer 
> within the timeout returns {{null}}, as the {{PollingConsumer}} contract says 
> ({{camel-jpa}} does the same; {{camel-http}} throws). The event-driven 
> consumer is not changed. CAMEL-22553 (open) plans a larger rework of the 
> connection code; this change is independent of it.
> The upgrade guide for 4.23 gets a note, which also says how a periodically 
> polling route can go on while the PLC is unreachable ({{onException}}, 
> {{doTry}}). With the fix the 6 tests pass, and the module suite passes (23 
> tests).
> Affected: 4.14.x, 4.18.x and main (same code).
> Duplicate check (2026-10-03): JIRA text "plc4x" (10 issues: CAMEL-24171, 
> 22491, 20871, 19199, 18861, ...): none about failures reported as success. 
> GitHub pull requests "plc4x": none open about the component.
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to