You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Claus Ibsen (Jira)" <ji...@apache.org> on 2026/10/03 08:17:00 UTC

[jira] [Assigned] (CAMEL-25276) camel-pubnub - a consumer receives the messages of the other channels of a shared PubNub client, every route restart adds another listener (messages received twice), and removing a route destroys the shared client

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

Claus Ibsen reassigned CAMEL-25276:
-----------------------------------

    Fix Version/s: 4.23.0
         Assignee: shashank

> camel-pubnub - a consumer receives the messages of the other channels of a shared PubNub client, every route restart adds another listener (messages received twice), and removing a route destroys the shared client
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25276
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25276
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-pubnub
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>             Fix For: 4.23.0
>
>
> A PubNub client hands every message and presence event it receives to all its listeners, whatever the channel. Since CAMEL-16142 the client can be autowired (one {{PubNub}} bean in the registry is used by every {{pubnub:}} endpoint), or referenced with {{pubnub=#bean}}. On main:
> # *Cross-talk.* {{PubNubConsumer}} adds a {{SubscribeCallback}} to the client and the callback does not look at the channel. With two routes {{from("pubnub:alpha")}} and {{from("pubnub:beta")}} on a shared client, a message published on {{alpha}} is received by both routes (the {{CamelPubNubChannel}} header says {{alpha}} in the {{beta}} route).
> # *Duplicates after a restart.* The consumer adds a new callback on every start and resume and never removes it ({{doStop}} only unsubscribes the channel). The endpoint, and so its client, survives a route stop, so after a stop and start of the route (route controller, supervising controller, {{master:}} / clustered route policy, suspend and resume) every message is received twice, once more per restart. This also happens without a shared client. The callbacks of the stopped consumer stay registered for the life of the client.
> # *Removing a route destroys the shared client.* {{PubNubEndpoint.doStop}} calls {{pubnub.destroy()}} also when the client came from the registry. Removing a route stops and removes the endpoints that only it uses, so removing the {{alpha}} route destroys the client that the {{beta}} route and the producers still use (and the endpoint forgets the client: a later start would build its own one from the endpoint options).
> h3. Reproduction
> {{PubNubConsumerListenerTest}}: two routes on {{pubnub:alpha?pubnub=#sharedPubnub}} and {{pubnub:beta?pubnub=#sharedPubnub}}, where {{sharedPubnub}} is a real PubNub 13 client (a subclass of {{PubNubForJavaImpl}} that counts {{destroy()}} calls); the test hands a message to the client's listeners through its {{ListenerManager}}, as the subscribe loop does:
> * message on {{alpha}}: {{mock:beta}} receives it ({{Expected: <0> but was: <1>}});
> * stop and start the {{alpha}} route, one message: received twice ({{Expected: <1> but was: <2>}});
> * remove the {{alpha}} route: the shared client is destroyed ({{expected: <0> but was: <1>}}).
> h3. Proposed fix
> * {{PubNubConsumer}} keeps its callback, removes it from the client when it stops or is suspended, and ignores events whose channel (or wildcard subscription, such as {{news.*}}) is not one of the consumer's channels (a comma separated channel option, which the client subscribes to as separate channels, is matched per channel). Presence events carry the channel without {{-pnpres}}, so the same check applies.
> * {{PubNubEndpoint}} remembers whether it created the client and destroys only that one; a client from the registry is left to the application that created it.
> With the fix the new test (7 tests: the three above fail on main, and so does a fourth that checks a wildcard subscription ({{news.*}}) and a presence event, which go to the other route too on main; "comma separated channels", "no message after stop" and "the endpoint still destroys its own client" are guards) and the camel-pubnub suite (21 tests) pass. The upgrade guide gets a note: a route no longer gets the other channels' messages, and a client from the registry is no longer destroyed by Camel.
> Affected: 4.14.x, 4.18.x and main (the callback is added the same way since the first version of the component; the client is autowired since 3.8, CAMEL-16142).
> Duplicate check (2026-10-02): JIRA component camel-pubnub and text "pubnub" (17 issues): only the feature, upgrade and build tickets (CAMEL-11136, 16142, 16708, 19005, ...). GitHub pull requests "pubnub", "PubNubConsumer", "PubNubEndpoint": only dependency bumps and the v10 upgrade (#15685).
> _Filed with Claude Code on behalf of allthingssecurity._



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