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

Serdar Gökay resolved CAMEL-25695.
----------------------------------
    Fix Version/s: 4.24.0
       Resolution: Fixed

Fixed by the CAMEL-25694 change: apache/camel#27956 (merged 2026-10-23, commit 
33075400207) replaces handleAsync() with whenCompleteAsync() in 
SubscriptionManager.write(), call(), readValues() and browse(), so an 
exceptional completion of readValues() now reaches MiloClientProducer and fails 
the exchange instead of completing with a null body. 
SubscriptionManagerExceptionPropagationTest covers the readValues() path.

> camel-milo - awaited readValues service failures are reported as success
> ------------------------------------------------------------------------
>
>                 Key: CAMEL-25695
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25695
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-milo
>    Affects Versions: 4.22.1
>         Environment: Camel 4.22.1; Eclipse Milo 1.1.6; OpenJDK 25.0.4; Maven 
> 3.9.16; macOS arm64. Attached reproduction uses a real loopback Milo OPC UA 
> server. Independent network confirmation used asyncua 1.1.8 on Python 3.12 
> and a loopback TCP relay. No physical PLC or production deployment.
>            Reporter: Serdar Gökay
>            Priority: Minor
>             Fix For: 4.24.0
>
>         Attachments: camel-milo-readvalues-failure-reproducer.zip
>
>
> h3. Problem
> An awaited producer read selected by {{CamelMiloNodeIds}} can fail at the OPC 
> UA service/transport layer while the Camel exchange completes successfully 
> with a null body. The success continuation runs and configured redelivery, 
> {{onException}} and dead-letter handling are skipped.
> Reproduced on released Camel 4.22.1 / Eclipse Milo 1.1.6. Both 
> {{CamelMiloAwait=true}} and {{defaultAwaitWrites=true}} reproduce the issue. 
> This concerns producer reads, not subscription-consumer delivery. Related 
> write/call finding: CAMEL-25694.
> h3. Reproduction
> The attached standalone Maven project starts its own real loopback TCP OPC UA 
> server. It does not mock the client, futures or transport, and does not patch 
> Camel classes.
> {code:bash}
> mvn -B -ntp -Duser.language=en -Duser.country=US 
> -Dtest=SingleNodeReadContractTest test
> mvn -B -ntp -Duser.language=en -Duser.country=US 
> -Dtest=AwaitedReadContractTest test
> {code}
> # Establish a connection and successfully read the test node(s); verify 
> values and Good statuses.
> # Make a subsequent awaited read. The real server returns a {{Bad_Timeout}} 
> ServiceFault for that read.
> # Inspect the exchange and route counters:
> {noformat}
> READ_CONTRACT_RESULT camel=4.22.1 milo=1.1.6 mode=BAD_TIMEOUT
> reads=1 redeliveries=0 downstream=1 failed=false exception=null body=null
> {noformat}
> Both desired-contract tests fail specifically because the exchange exception 
> is missing. The minimal reproduction needs only one node. A direct Milo SDK 
> client against the same server/fault throws {{UaException}} with the matching 
> status.
> The attachment also contains 14 characterization/control tests, run with 
> {{mvn test '-Dtest=*EvidenceTest'}}. These pass by asserting the observed 
> behavior, including the defect; they do not demonstrate a fix. They cover 
> both await settings, {{Bad_Timeout}} and {{Bad_SessionClosed}} service 
> responses, native SDK controls, successful list types/order/duplicates, 
> namespace-URI addressing, per-node bad status, retry/DLQ/onException controls 
> and explicitly non-awaited behavior.
> Independent network testing used a normal asyncua OPC UA server behind a 
> loopback TCP relay. Dropping requests, dropping responses or closing the 
> established connection produced the same null-success result. Nine network 
> cases were run twice: four healthy controls passed and all fourteen failure 
> executions failed the desired contract. These network scripts are separate 
> from the attached minimal Maven reproduction.
> h3. Expected behavior and scope
> When an awaited read completes exceptionally, preserve that exceptional 
> completion so {{MiloClientProducer}} can fail the exchange and configured 
> Camel error handling can run. Preserve successful {{List<DataValue>}} results 
> and ordinary per-node bad statuses, such as {{Bad_NodeIdUnknown}}, inside 
> their individual {{DataValue}} results.
> An already-disconnected manager has a separate exceptional {{No connected}} 
> path; the reproduction deliberately establishes a healthy connection first. 
> Explicit non-await mode is not the awaited defect. {{Bad_SessionClosed}} is a 
> controlled service-error response, not an actual session-expiry simulation. 
> No physical PLC or subscription behavior is claimed.
> h3. Cause and proposed direction
> In outer {{SubscriptionManager.readValues}}, {{handleAsync}} calls 
> {{handleConnectionFailure(error)}} and then returns {{nodes}}, which is null 
> after exceptional completion. That converts a failed future into normal 
> completion. The producer's existing awaited callback consequently sees no 
> throwable.
> Proposed change, keeping the executor and recovery callback:
> {code:java}
> return this.connected.readValues(nodeIds).whenCompleteAsync((nodes, error) -> 
> {
>     if (error != null) {
>         handleConnectionFailure(error);
>     }
> }, this.executor);
> {code}
> This is a proposed direction, not an applied or verified fix. The completion 
> observer preserves both successful lists and exceptional completion.
> Pinned released source: 
> [SubscriptionManager.readValues|https://github.com/apache/camel/blob/c056bef67cdfeffdc0ad7255e5e052cab71f2921/components/camel-milo/src/main/java/org/apache/camel/component/milo/client/internal/SubscriptionManager.java#L1014-L1032]
>  and 
> [MiloClientProducer|https://github.com/apache/camel/blob/c056bef67cdfeffdc0ad7255e5e052cab71f2921/components/camel-milo/src/main/java/org/apache/camel/component/milo/client/MiloClientProducer.java#L77-L103].
> _This report and reproduction are AI-generated with Codex on behalf of GitHub 
> user etzel-mes._



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

Reply via email to