shashank created CAMEL-25742:
--------------------------------

             Summary: camel-coap - an observe=true consumer never cancels its 
observation, so after a route stop and start every notification is routed twice
                 Key: CAMEL-25742
                 URL: https://issues.apache.org/jira/browse/CAMEL-25742
             Project: Camel
          Issue Type: Bug
          Components: camel-coap
            Reporter: shashank
            Assignee: shashank


A route {{from("coap://host:5683/sensor?observe=true")}} uses {{CoAPObserver}}. 
On start it calls {{client.observe(this)}} (RFC 7641) and drops the returned 
{{CoapObserveRelation}}. The class has no {{doStop}} (main 826a664c5f16), so 
stopping the consumer does nothing to the observation:
* the server keeps the stopped consumer as an observer, and each notification 
is still delivered to it; while the route is stopped each one fails with 
{{RouteStoppingException}} and is logged as a WARN by the consumer;
* when the route is started again, Camel creates a new consumer, which observes 
the resource a second time. The stopped consumer still holds the route's 
processor, which is started again, so from then on each notification is routed 
twice, and once more for each further stop / start;
* {{onError}} observes again even after a stop;
* the {{CoapClient}} of a stopped consumer is never shut down.

Trigger: default options, a route with an {{observe=true}} consumer that is 
stopped and started again ({{camel cmd stop-route}} / {{start-route}}, JMX / 
management, the route controller API). A route reload removes the route 
instead; the old consumer's observation is then also left (a WARN per 
notification, and a client that is not shut down per reload), but it does not 
route into the new route (read, not tested).

h3. Reproduction

New test {{CoAPObserveRestartTest}} (2 tests, Camel CoAP server with an 
observable resource in the same JVM, no external service):
* stop and start the observer route, then change the resource once: the 
notification must be routed once. On main it is routed twice: {{mock://observed 
Received message count. Expected: <1> but was: <2>}} (3 of 3 runs);
* after {{stopRoute("observer")}} the resource must have no observer left, 
after {{startRoute}} exactly one. On main the server still holds the stopped 
consumer's observation ({{ConditionTimeout ... was not fulfilled within 10 
seconds}} at the {{observerCount() == 0}} wait, 3 of 3 runs).

h3. Proposed fix

Keep the relation returned by {{observe}}, and in {{doStop}} cancel it with 
{{proactiveCancel()}} (Californium cancels the observation in the client at 
once, so a later notification is not delivered, and sends the deregistration to 
the server), then shut the client down; {{onError}} observes again only while 
the consumer is running. With the fix the camel-coap tests pass: 78 run, 0 
failures, 0 errors, 0 skipped.

Not changed: the server side {{CoAPConsumer}} also has no {{doStop}} (a stopped 
route keeps answering requests until its path is taken by a new consumer); its 
client {{CoapEndpoint}} (socket and threads) is also not destroyed by 
{{CoapClient.shutdown()}}. Both are left for a follow-up.

Affected: main (tested); camel-4.23.x, camel-4.22.x, camel-4.18.x and 
camel-4.14.x have the same {{CoAPObserver}} without {{doStop}} (read, not run). 
The observe consumer exists since CAMEL-19280.

Duplicate check (2026-10-17): JIRA text "CoAPObserver", "coap observe stop", 
"coap observe cancel": nothing related. GitHub pull requests "coap observe": 
none about the observer lifecycle.

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to