Skip to content

CAMEL-24811: camel-servlet - fix async servlet completing before the route finishes (backport 4.22.x) - #26596

Merged
davsclaus merged 1 commit into
apache:camel-4.22.xfrom
Croway:CAMEL-24811-servlet-async-race-4.22.x
Sep 18, 2026
Merged

davsclaus merged 1 commit into
apache:camel-4.22.xfrom
Croway:CAMEL-24811-servlet-async-race-4.22.x

Conversation

@Croway

@Croway Croway commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

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 with async=true&useContinuation=false) completed the AsyncContext before 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 a protected request attribute constant. No upgrade guide entry needed.

Draft until #26584 is reviewed and merged on main.

Claude Code on behalf of Croway

…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>
@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@Croway
Croway marked this pull request as ready for review September 18, 2026 13:09
@github-actions

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-http-common
  • components/camel-jetty
  • components/camel-servlet

ℹ️ Dependent modules were not tested because the total number of affected modules exceeded the threshold (50). Use the test-dependents label to force testing all dependents.


🔬 Scalpel shadow comparison — Scalpel: 66 tested, 29 compile-only — current: 66 all tested

Maveniverse Scalpel detected 95 affected modules (current approach: 66).

⚠️ Modules only in Scalpel (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 66 modules (3 direct + 63 downstream), skip tests for 29 (generated code, meta-modules)

Modules Scalpel would test (66)
  • camel-a2a
  • camel-as2
  • camel-atmosphere-websocket
  • camel-clickup
  • camel-consul
  • camel-cxf-rest
  • camel-cxf-soap
  • camel-cxf-spring-rest
  • camel-cxf-spring-soap
  • camel-cxf-spring-transport
  • camel-cxf-transport
  • camel-graphql
  • camel-http
  • camel-http-common
  • camel-java-joor-dsl
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-jetty
  • camel-jetty-common
  • camel-jsonpath
  • camel-kamelet
  • camel-knative-http
  • camel-kubernetes
  • camel-launcher-container
  • camel-lra
  • camel-mcp-server
  • camel-micrometer-observability
  • camel-micrometer-prometheus
  • camel-netty-http
  • camel-oauth
  • camel-observability-services
  • camel-openapi-validator
  • camel-opentelemetry
  • camel-opentelemetry2
  • camel-platform-http
  • camel-platform-http-jolokia
  • camel-platform-http-main
  • camel-platform-http-vertx
  • camel-quickfix
  • camel-rest-openapi
  • camel-restdsl-openapi-plugin
  • camel-sap-netweaver
  • camel-servlet
  • camel-slack
  • camel-soap
  • camel-spring-rabbitmq
  • camel-telegram
  • camel-telemetry
  • camel-telemetry-dev
  • camel-test-main-junit5
  • camel-test-main-junit6
  • camel-undertow
  • camel-undertow-spring-security
  • camel-vertx-http
  • camel-webhook
  • camel-whatsapp
  • camel-xml-io-dsl
  • camel-xml-jaxb-dsl
  • camel-xml-jaxb-dsl-test-definition
  • camel-xml-jaxb-dsl-test-spring
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
  • camel-zookeeper
Modules with tests skipped (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • components/camel-jetty: 1 test(s) disabled on GitHub Actions
Build reactor — dependencies compiled but only changed modules were tested (95 modules)
  • Camel :: AI :: A2A
  • Camel :: AI :: MCP Server
  • Camel :: AS2 :: Component
  • Camel :: All Components Sync point
  • Camel :: Assembly
  • Camel :: Atmosphere WebSocket Servlet
  • Camel :: CXF :: REST
  • Camel :: CXF :: REST :: Spring
  • Camel :: CXF :: SOAP
  • Camel :: CXF :: SOAP :: Spring
  • Camel :: CXF :: Transport
  • Camel :: CXF :: Transport :: Spring
  • Camel :: Catalog :: CSimple Maven Plugin (deprecated)
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Lucene (deprecated)
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: ClickUp
  • Camel :: Common Telemetry
  • Camel :: Component DSL
  • Camel :: Consul
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: GraphQL
  • Camel :: HTTP
  • Camel :: HTTP :: Common
  • Camel :: Integration Tests
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: JSon Path
  • Camel :: Java DSL with jOOR
  • Camel :: Jetty
  • Camel :: Jetty :: Common
  • Camel :: Kamelet
  • Camel :: Kamelet Main
  • Camel :: Knative HTTP
  • Camel :: Kubernetes
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: Long-Running-Action
  • Camel :: Maven Plugins :: OpenApi REST DSL Generator
  • Camel :: Micrometer :: Observability 2
  • Camel :: Micrometer :: Prometheus
  • Camel :: Netty HTTP
  • Camel :: OAuth
  • Camel :: Observability Services
  • Camel :: OpenAPI :: Validator
  • Camel :: OpenTelemetry (deprecated)
  • Camel :: Opentelemetry 2
  • Camel :: Platform HTTP
  • Camel :: Platform HTTP :: Jolokia
  • Camel :: Platform HTTP :: Main
  • Camel :: Platform HTTP :: Vert.x
  • Camel :: QuickFIX/J
  • Camel :: REST OpenApi
  • Camel :: SAP NetWeaver
  • Camel :: SOAP
  • Camel :: Servlet
  • Camel :: Slack
  • Camel :: Spring RabbitMQ
  • Camel :: Telegram
  • Camel :: Telemetry :: Dev
  • Camel :: Test :: Main :: JUnit5
  • Camel :: Test :: Main :: JUnit6
  • Camel :: Undertow
  • Camel :: Undertow Spring Security
  • Camel :: Vert.x :: HTTP
  • Camel :: Webhook
  • Camel :: Whatsapp
  • Camel :: XML DSL Jaxb :: Test :: Definition
  • Camel :: XML DSL Jaxb :: Test :: Spring
  • Camel :: XML DSL with camel-xml-io
  • Camel :: XML DSL with camel-xml-jaxb
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin
  • Camel :: Zookeeper

⚙️ View full build and test results

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@davsclaus davsclaus added this to the 4.22.2 milestone Sep 18, 2026
@davsclaus davsclaus added the bug Something isn't working label Sep 18, 2026
@davsclaus
davsclaus merged commit 66d6fb5 into apache:camel-4.22.x Sep 18, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants