You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "shashank (Jira)" <ji...@apache.org> on 2026/10/20 05:11:00 UTC
[jira] [Work started] (CAMEL-25854) camel-undertow - rest-dsl and plain undertow consumers on the same port: only the kind that registers first is served, and stopping the last consumer of one kind stops the server for the other
[ https://issues.apache.org/jira/browse/CAMEL-25854?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Work on CAMEL-25854 started by shashank.
----------------------------------------
> camel-undertow - rest-dsl and plain undertow consumers on the same port: only the kind that registers first is served, and stopping the last consumer of one kind stops the server for the other
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25854
> URL: https://issues.apache.org/jira/browse/CAMEL-25854
> Project: Camel
> Issue Type: Bug
> Components: camel-undertow
> Reporter: shashank
> Assignee: shashank
> Priority: Major
>
> {{DefaultUndertowHost}} (main 20cdb309f7d0) runs one Undertow server per host and port for the consumers of the component. It has two handlers: {{RestRootHandler}} for the rest-dsl consumers and {{CamelRootHandler}} for the plain {{undertow:}} endpoints. The server is given only one of them, chosen from the first consumer that registers on the port:
> {code:java}
> // use the rest handler as its a rest consumer
> serverHandler = consumer != null && consumer.isRest() ? restHandler : rootHandler;
> {code}
> A later consumer of the other kind is still added to its own handler ({{registerHandler}}, the last if/else), but the server never calls that handler. Its route starts normally and logs nothing, and every request to it gets 404 "No matching path found". For example, take {{restConfiguration().component("undertow").port(8080)}} with {{rest("/users").get("{id}")}} next to {{from("undertow:http://0.0.0.0:8080/health")}}. Only the kind whose route starts first is served. A plain route usually starts first, because routes built from the rest-dsl are added after the plain routes of the same builder, so the REST API is the part that answers 404.
> {{unregisterHandler}} also checks only one kind: it stops the server when the kind of the consumer being removed has no consumer left ({{restHandler.consumers() <= 0}} or {{rootHandler.isEmpty()}}), even if consumers of the other kind are still registered. Stopping or reloading the last REST route therefore stops the server under the started plain undertow routes, and the reverse also happens. Their clients get connection refused until those routes are restarted.
> *Fix*: the server always calls the handler of the plain endpoints. Its default handler (used when no plain endpoint matches) is now the rest-dsl handler instead of {{NotFoundHandler}}. The rest-dsl handler answers 404 "No matching path found" (the same response as {{NotFoundHandler}}), or 405 when none of its consumers matches either. The server stops only when neither kind has a consumer left. When a path is served by both a plain endpoint and a rest-dsl consumer, the plain endpoint takes it. Before the fix only one kind was ever served, so no working setup changes.
> *Tests*: new {{RestUndertowAndPlainConsumerSamePortTest}} (a rest-dsl GET {{/users/{id}}} and a plain {{undertow:http://localhost:port/plain}} on the same port). On main all 3 tests fail. {{testBothKindsAreServed}} and {{testPlainConsumerAddedAfterRestConsumer}} fail with {{/users/123 ==> expected: <200> but was: <404>}}. {{testServerKeepsServingWhenOneKindStops}} stops the REST route and then calls {{/plain}}, which fails with {{expected: <200> but was: <null>}} because the server was stopped and the connection was refused. With the fix all 3 pass, and the camel-undertow unit tests run 238 tests with 0 failures (1 skipped).
> *How it was found*: a review of shared per-port server state in the HTTP consumer components, after the per-owner resource fixes CAMEL-25849 and CAMEL-25850. The JUnit test above confirmed it.
> *Affected*: main, camel-4.23.x, camel-4.22.x and camel-4.18.x all have the same handler choice and the same stop condition in {{DefaultUndertowHost}}. This was checked by reading the code, not by running it.
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)