[
https://issues.apache.org/jira/browse/CAMEL-24788?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen resolved CAMEL-24788.
---------------------------------
Resolution: Fixed
> camel-vertx-websocket: a shared websocket host is unregistered when the first
> of its consumers stops
> ----------------------------------------------------------------------------------------------------
>
> Key: CAMEL-24788
> URL: https://issues.apache.org/jira/browse/CAMEL-24788
> Project: Camel
> Issue Type: Bug
> Components: camel-vertx-websocket
> Reporter: Andrea Cosentino
> Assignee: Andrea Cosentino
> Priority: Major
> Fix For: 4.23.0
>
>
> h3. Summary
> All {{vertx-websocket}} consumers bound to the same host and port share one
> {{VertxWebsocketHost}}, but the host is dropped from the component registry
> as soon as the *first* of those consumers stops. Every consumer that stops
> afterwards is silently ignored, its Vert.x route is never removed, and the
> HTTP server it runs on is never stopped.
> h3. Detail
> {{VertxWebsocketHostKey}} is {{\{host, port\}}} only (lines 25-26), so
> {{connectConsumer}} shares a single host across every path on that port:
> {code:java}
> VertxWebsocketHost host = vertxHostRegistry.computeIfAbsent(hostKey, key -> {
> ... });
> host.connect(consumer);
> {code}
> ({{VertxWebsocketComponent}} line 167)
> but {{disconnectConsumer}} removes that shared host on the first stop:
> {code:java}
> VertxWebsocketHost vertxWebsocketHost = vertxHostRegistry.remove(hostKey);
> if (vertxWebsocketHost != null) {
> vertxWebsocketHost.disconnect(configuration.getWebsocketURI().getPath());
> }
> {code}
> ({{VertxWebsocketComponent}} line 205)
> With two consumers, {{/a}} and {{/b}}, on the same port:
> * stopping the {{/a}} route removes the shared host from the registry, then
> {{disconnect("/a")}} removes only that route.
> {{VertxWebsocketHost.disconnect}} (line 166) stops the server only once its
> own {{routeRegistry}} is empty, and {{/b}} is still in it, so the server
> keeps running - correctly, at that point;
> * stopping the {{/b}} route then finds *nothing* in the registry: {{remove}}
> returns null, the null guard skips, and route {{/b}} is never removed. **The
> server carries on listening after every Camel route is stopped.**
> * starting a consumer on that host and port again builds a *second*
> {{VertxWebsocketHost}} with a new Router and calls {{start()}} on a port the
> first server still holds.
> {{VertxWebsocketComponent.doStop}} (line 157) closes Vert.x only when Camel
> created it, so when the application supplies its own {{Vertx}} or {{Router}}
> - the usual arrangement under Spring Boot and Quarkus - nothing ever tears
> the server down.
> h3. Two smaller problems in the same lifecycle
> * {{VertxWebsocketHost}} line 54 keeps {{routeRegistry}} in a plain
> {{HashMap}}, mutated by {{connect}} and {{disconnect}}, i.e. on route start
> and stop. The field right below it is a {{CopyOnWriteArrayList}} carrying an
> explicit {{// thread-safe}} comment, so the difference looks accidental
> rather than considered. Route start/stop is concurrent under the supervising
> route controller.
> * {{VertxWebsocketHost.disconnect}} lines 164-165 do
> {{routeRegistry.remove(path)}} and then {{route.remove()}} with no null
> check, so an unknown or repeated path throws a {{NullPointerException}}.
> Found by a source audit of {{components/camel-vertx}} at be3dd651866f.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)