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/02 07:53:00 UTC

[jira] [Updated] (CAMEL-25253) camel-dynamic-router - updating a subscription is ignored when the priority is unchanged, and duplicates the subscription when the priority changes

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

Claus Ibsen updated CAMEL-25253:
--------------------------------
    Fix Version/s: 4.23.0

> camel-dynamic-router - updating a subscription is ignored when the priority is unchanged, and duplicates the subscription when the priority changes
> ---------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25253
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25253
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>            Reporter: shashank
>            Priority: Minor
>             Fix For: 4.23.0
>
>
> The control endpoint and the JMX operations can update an existing subscription ({{update=true}}: "update the subscription (true), or add a new one (false)"). {{DynamicRouterFilterService.addFilterForChannel}} checks that a filter with the id exists and then only does
> {code:java}
> filters.add(filter);                         // ConcurrentSkipListSet ordered by FILTER_COMPARATOR (priority, then id)
> filterStatistics.add(filter.statistics());
> {code}
> The set compares filters by priority and id only, so:
> * *same priority:* the new filter is "equal" to the existing one, {{add}} returns false and the old filter stays. The update (new predicate, new destination) is silently ignored, while the operation returns the subscription id as if it had succeeded;
> * *other priority:* both filters stay in the set. The subscription now routes with its old and its new definition: in {{allMatch}} mode messages go to both destinations (duplicates), in {{firstMatch}} mode the old definition can still win; and {{getFilterById}} returns either.
> In addition, {{filterExists}} is computed with {{filterMap.get(channel).stream()}} as soon as any channel has filters, so a subscription for a channel that has none yet fails with a {{NullPointerException}}.
> The existing unit test of the update passes only because its factory returns the same mock for the old and the new filter, whose priority it changes in place.
> h3. Reproduction
> With the default filter factory:
> {code:java}
> DynamicRouterFilterService service = new DynamicRouterFilterService();
> service.initializeChannelFilters("test");
> service.addFilterForChannel("sub", 1, PredicateBuilder.constant(true), "mock:old", "test", false);
> service.addFilterForChannel("sub", 1, PredicateBuilder.constant(true), "mock:new", "test", true);   // returns "sub"
> service.getFilterById("sub", "test").endpoint();                                                    // "mock:old"
> service.addFilterForChannel("sub", 10, PredicateBuilder.constant(true), "mock:new", "test", true);
> service.getFiltersForChannel("test").size();                                                        // 2
> service.addFilterForChannel("other", 1, PredicateBuilder.constant(true), "mock:other", "other", false); // NullPointerException
> {code}
> A unit test with these three cases fails on main.
> h3. Proposed fix
> Get (or create) the channel's filter set and statistics list first; on an update remove the existing filter with that id, then add the new filter. The statistics of the replaced filter stay in the list, as {{removeFilterById}} keeps those of a removed filter on purpose ("the statistics still represent actions that happened"), so after an update the list looks as after an unsubscribe and a subscribe with the same id. With the fix the new test and the camel-dynamic-router suite pass (137 unit tests, 21 integration tests).
> Affected: 4.14.x, 4.18.x and main (same code since CAMEL-20302, 4.4).
> Duplicate check (2026-10-01): JIRA text "dynamic-router" (54 issues) and "dynamic router" with "update": CAMEL-21407 (unsubscribe), CAMEL-23735 (aggregation), CAMEL-24576 (control predicate), none about update. GitHub pull requests: none open on the component.
> _Filed with Claude Code on behalf of allthingssecurity._



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