shashank created CAMEL-26453:
--------------------------------

             Summary: camel-dynamic-router - a route that sends to a Dynamic 
Router channel cannot be added again after it was removed
                 Key: CAMEL-26453
                 URL: https://issues.apache.org/jira/browse/CAMEL-26453
             Project: Camel
          Issue Type: Bug
          Components: camel-core
            Reporter: shashank
            Assignee: shashank


{{DynamicRouterEndpoint.doInit()}} creates the {{DynamicRouterProcessor}} of 
its channel and adds it to the component with 
{{DynamicRouterComponent.addRoutingProcessor(channel, processor)}}, which fails 
when the channel already has a processor ({noformat}Dynamic Router can have 
only one processor per channel; channel 'orders' already has a 
processor{noformat}). Nothing ever removes the processor again, except the 
{{doShutdown}} of the component (when the CamelContext shuts down).

When a route that sends to {{dynamic-router:orders}} is removed, Camel stops 
and removes the endpoints that only that route used, so the endpoint is gone 
but its processor stays in the component. Then:
* adding the route again fails with {{FailedToCreateRouteException}} ... 
{{already has a processor}} (a route reload in development mode replaces the 
routes of a changed file by removing and adding them, and fails the same way);
* a {{toD("dynamic-router:${header.channel}")}} in another route, which used 
the same endpoint while the removed route existed (a {{toD}} endpoint does not 
keep an endpoint in use), creates the endpoint again on its next message and 
fails every exchange with {{ResolveEndpointFailedException}};
* the same happens when the producer cache of a {{toD}} evicts the endpoint and 
a later message creates it again.

The subscriptions of the channel are kept by the component (filter service), so 
the channel would work again as soon as the new endpoint can register its 
processor.

Reproducer (on main 4ab42b192b26):
{code:java}
from("direct:subscribe").to("dynamic-router-control:subscribe?subscribeChannel=orders&subscriptionId=all&destinationUri=mock:result&priority=1&predicate=true");
from("direct:start").routeId("router").to("dynamic-router:orders");

context.getRouteController().stopRoute("router");
context.removeRoute("router");
context.addRoutes(sameRouterRoute);   // FailedToCreateRouteException: ... 
channel 'orders' already has a processor
{code}

The same check makes an endpoint that is stopped and started again fail, as 
{{BaseService.start}} runs {{init}} again after a stop.

*Proposal*
* The component keeps one processor per channel, with the endpoint that uses 
it. An endpoint with the same URI takes the same processor (a route removed and 
added again, a reload, a {{toD}} re-creating the endpoint, an endpoint started 
again); an endpoint with another URI still fails while the endpoint that uses 
the processor is in use, and replaces the processor once that endpoint is 
stopped (the new processor is created first; the old {{RecipientList}} is 
stopped, and its thread pool is only shut down with the component so that 
exchanges another route still has in flight in it are not interrupted; replaced 
processors are kept until the component shuts down).
* Nothing is stopped when an endpoint stops, so a send that still uses a 
removed or evicted endpoint keeps routing, and no processor or 
{{parallelProcessing}} pool is created per re-creation.
* The producer fails the exchange with a clear exception naming the channel 
when the channel has no processor, instead of a {{NullPointerException}}; 
{{doShutdown}} of the component stops the processors (it passes the map itself 
to {{ServiceHelper.stopAndShutdownService}} today, which stops nothing).
* Tests: remove the route and add it again (with the same and with other 
options), a {{toD}} after the route was removed, a stop and start of the 
endpoint, a second endpoint for the channel, a send through a removed endpoint, 
an exchange in flight with {{parallelProcessing}}.

_Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to