allthingssecurity opened a new pull request, #28592: URL: https://github.com/apache/camel/pull/28592
# Description [CAMEL-26084](https://issues.apache.org/jira/browse/CAMEL-26084) When the CamelContext stops while a vertx-http request is in flight (the graceful shutdown timeout runs out, or an application stops its context during a slow call), the exchange is never completed: `callback.done` is never called, and the caller waits for ever (a `ProducerTemplate` request, an upstream synchronous consumer, a thread of a scheduled job). netty-http and undertow fail such an exchange within about a second of the stop. Root cause, checked with logging in the result handler on main: 1. `VertxHttpEndpoint.doStop` closes the `WebClient`. Vert.x then fails the pending request with `HttpClosedException: Connection was closed` and calls the result handler of the producer on its event loop. 2. By then `VertxHttpComponent.doStop` has set its `vertx` field to `null` (also for a Vert.x it does not manage), and `getVertx()` of a stopped component returns `null`. 3. The handler calls `getEndpoint().getVertx().executeBlocking(...)`, which throws a `NullPointerException` inside the Vert.x handler, so the task that calls `callback.done(false)` is never submitted. The log line from the handler on main, for a Vert.x managed by Camel and for one set in the registry alike: `ok=false cause=io.vertx.core.http.HttpClosedException: Connection was closed vertx=null`. Changes (`VertxHttpProducer.createResultHandler`): - The Vert.x is taken when the request is sent, not when its result arrives, so the handler still submits the task (with the `HttpClosedException` of the request, which the binding sets on the exchange) after the component let go of its Vert.x. In the stop cases I tried, the worker pool then runs the task, also while a Vert.x managed by Camel is closing and when the application closes its own Vert.x during the call (that case already completes on main). - A second path: when the worker pool of the Vert.x is already shut down as the result arrives, the task is refused and never runs. Vert.x 5.2.1 (the `vertx-version` of the build; javap of `io.vertx.core.impl.ExecuteBlocking.executeBlocking`) catches the `RejectedExecutionException`, fails the future of the task (`WorkerTask.reject`) and throws the exception again, so the handler now catches it and completes the exchange with it. An `onFailure` handler on the future completes it as well for a future that fails without a throw. An `AtomicBoolean` makes sure `callback.done` runs once, whichever of the task, the catch and `onFailure` gets there first. - The endpoint always creates and closes its own `WebClient`, and closing it fails every pending request, so there is no request left for a `doStop` to complete. - No option, generated file or upgrade guide change: the exchange used to hang, now it fails with the `HttpClosedException`. - Backport: `createResultHandler` and the two `doStop` methods are the same on camel-4.22.x, 4.18.x and 4.14.x (read, not run). Tests: - New `VertxHttpStopDuringCallCompletesTest`, 3 tests. A JDK `HttpServer` receives the request and answers only when the test releases it; the CamelContext (shutdown timeout 1 s) is stopped once the server has the request. The reply future must fail within 20 s with an `HttpClosedException` in its cause chain. - `exchangeCompletesWhenTheCamelContextStopsDuringTheCall`: Vert.x created and closed by the component. - `exchangeCompletesWhenTheCamelContextStopsDuringTheCallWithAVertxNotManagedByCamel`: a Vert.x bound in the registry, which Camel does not close; only the web client is closed. Both fail on main: `Unexpected exception type thrown, expected: <java.util.concurrent.ExecutionException> but was: <java.util.concurrent.TimeoutException>`. - `exchangeCompletesWhenTheWorkerPoolRefusesTheResponseTask`: a registry Vert.x built with an `ExecutorServiceFactory` (`VertxBootstrap`), whose worker pool the test shuts down once the server has the request; then the server answers. The reply must fail with a `RejectedExecutionException`. It fails without the second change (the previous version of this branch, and the fix without the catch), with the same `TimeoutException`; the CamelContext is not stopped here, so it does not depend on the first change. - Unit tests of camel-vertx-http with the fix: 111 run, 0 failures, 1 skipped. The formatter and import-sort plugins ran. # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it): [CAMEL-26084](https://issues.apache.org/jira/browse/CAMEL-26084). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built camel-vertx-http and ran its tests, including the formatter and import-sort plugins. No generated file changes. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
