[
https://issues.apache.org/jira/browse/CAMEL-25253?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen reassigned CAMEL-25253:
-----------------------------------
Assignee: shashank
> 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
> Assignee: 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)