CAMEL-24811: camel-servlet - fix async servlet completing before the route finishes (backport 4.22.x) - #26596
Conversation
…route finishes CamelServlet.doServiceAsync() (async=true without executorRef) completed the AsyncContext right after doService() returned, discarding the CompletionStage that doExecute() returns when the route continues on another thread. This races the container's async completion against the later writeResponse(), giving an IllegalStateException on the recycled response (Tomcat) or an empty/stale response. camel-jetty in async mode (async=true&useContinuation=false) hits the same path via super.doService(). doService() keeps its void signature (protected extension point, must stay binary compatible for backports); the in-flight stage is handed over via the CamelAsyncPromise request attribute and doServiceAsync() completes the AsyncContext only once it is done, mirroring doAsyncExecution(). Also: complete the AsyncContext in doAsyncExecution()'s error branch (onError always throws), and always write the response / finish the UoW when processAsync() fails synchronously or completes exceptionally. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 66 tested, 29 compile-only — current: 66 all testedMaveniverse Scalpel detected 95 affected modules (current approach: 66).
|
gnodet-bot
left a comment
There was a problem hiding this comment.
The core fix is sound — the promise-via-request-attribute handshake correctly defers context.complete() until the async route finishes, and tryAsyncProcess now always calls afterProcess (error or not).
One coverage gap: the executorRef code path (doAsyncExecution) is not covered by a new race test.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Backport of #26584 to
camel-4.22.x(straight cherry-pick, no conflicts).Fixes CAMEL-24811:
CamelServlet.doServiceAsync()(async=true without executorRef, and camel-jetty withasync=true&useContinuation=false) completed theAsyncContextbefore a route that resumes on another thread had written its response. The bug dates from CAMEL-11731 (Camel 3.7), so every LTS branch is affected.No API changes:
doService()keeps its signature, the in-flight stage is handed over via aprotectedrequest attribute constant. No upgrade guide entry needed.Draft until #26584 is reviewed and merged on
main.Claude Code on behalf of Croway