Croway opened a new pull request, #26584: URL: https://github.com/apache/camel/pull/26584
## Summary `CamelServlet.doServiceAsync()` (used when `async=true` and no `executorRef` is configured — the simplest, most common async servlet setup) called `AsyncContext.complete()` unconditionally right after `doService()` returned, discarding the `CompletionStage` that `doExecute()` returns when the route's processor genuinely completes on another thread (`AsyncProcessor.processAsync()`). This races the servlet container's async completion against the later `afterProcess()`/`writeResponse()` call: * On Tomcat this throws `IllegalStateException: The response object has been recycled and is no longer associated with this facade`. * Otherwise, the async context completes with whatever was (or wasn't) written yet, and the client gets a stale/empty response while the route keeps running in the background. Reproduced without any third-party client library: a route with `.delay(300).asyncDelayed()` behind `async=true`/no `executorRef`, serviced through an embedded Undertow container, returns `HTTP 200` with an **empty body** every time on `main` before this fix. The sibling path used when `executorRef` **is** configured (`doAsyncExecution()`) already does this correctly — it chains `AsyncContext.complete()` onto `promise.whenComplete(...)`. This bug predates 4.21/4.22: it was introduced by CAMEL-11731 (Camel 3.7) when true async processing was added to `doExecute()`, without updating the no-`executorRef` `doServiceAsync()` dispatch path to match. ## Changes * `doService()` now returns the `CompletionStage<?>` from `doExecute()` instead of discarding it. * `doServiceAsync()` completes the `AsyncContext` only once that stage completes, mirroring `doAsyncExecution()`. * Fixed the same `context.complete()` gap in `doAsyncExecution()`'s error branch (it was unreachable, since `onError()` always throws — so a synchronous exception there never completed the `AsyncContext`, only timed out). * `CamelContinuationServlet` (`camel-jetty`) and `CamelWebSocketServlet` (`camel-atmosphere-websocket`) are updated only for the new signature (`return null`) — both already manage their own async completion internally and are unaffected in behavior. * Added `ServletAsyncNoExecutorRefRaceTest` reproducing the bug with a genuinely-async route step, independent of any external service. ## Test plan - [x] New test `ServletAsyncNoExecutorRefRaceTest` fails before the fix (empty body), passes after - [x] `camel-servlet` full test suite passes - [x] `camel-jetty` `*Continuation*`/`*Async*` tests pass (no regression from the `CamelContinuationServlet` signature change) Fixes CAMEL-24811. _Claude Code on behalf of Croway_ 🤖 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]
