[
https://issues.apache.org/jira/browse/CAMEL-25314?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen resolved CAMEL-25314.
---------------------------------
Resolution: Fixed
Merged in https://github.com/apache/camel/pull/27390 (commit 8e4d1c2a0e84) for
4.23.0.
_Claude Code on behalf of davsclaus_
> camel-cxf, camel-cxfrs - a suspended consumer keeps accepting and routing new
> requests (graceful shutdown, suspendRoute, route policies)
> ----------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25314
> URL: https://issues.apache.org/jira/browse/CAMEL-25314
> Project: Camel
> Issue Type: Bug
> Components: camel-cxf, camel-cxfrs
> Reporter: shashank
> Assignee: shashank
> Priority: Minor
> Fix For: 4.23.0
>
>
> Since CAMEL-12870 {{CxfConsumer}} and {{CxfRsConsumer}} implement
> {{Suspendable}}: {{DefaultShutdownStrategy}} suspends them instead of
> stopping them, defers their shutdown until no exchange is inflight, and the
> CXF server stays up so the requests in flight can still send their responses.
> But neither consumer has suspend logic, and their invokers
> ({{CxfConsumer.CxfConsumerInvoker.invoke}},
> {{CxfRsInvoker.performInvocation}}) never check the status, so a suspended
> consumer keeps accepting and routing *new* requests:
> * graceful shutdown: with a steady flow of requests the number of inflight
> exchanges does not drop to 0, so the route (or the CamelContext) is only
> stopped at the shutdown timeout, and the requests in flight at that moment
> are forced; the requests accepted during the shutdown are processed by a
> stopping application;
> * {{suspendRoute}} (route controller, JMX) and the route policies that
> suspend the consumer ({{ThrottlingInflightRoutePolicy}},
> {{ThrottlingExceptionRoutePolicy}}): nothing is held back.
> The HTTP consumers (servlet, jetty, undertow, netty-http, platform-http)
> answer 503 (Service Unavailable) while they are suspended.
> h3. Reproduction
> {{CxfConsumerSuspendTest}} (camel-cxf-soap) and {{CxfRsConsumerSuspendTest}}
> (camel-cxf-rest), on main:
> {noformat}
> CxfConsumerSuspendTest.testSuspendedRouteRejectsRequests: suspendRoute, then
> a request
> A suspended route must not accept a request ==> Expected
> java.lang.Exception to be thrown, but nothing was thrown.
> CxfConsumerSuspendTest.testGracefulStopCompletesInflightAndRejectsNewRequests:
> request A blocks in the route,
> stopRoute (graceful) suspends the consumer, request B is sent
> A request received while stopping must be rejected ==> Expected
> java.lang.Exception to be thrown, but nothing was thrown.
> CxfRsConsumerSuspendTest.testSuspendedRouteRejectsRequests:
> A suspended route must answer 503 ==> expected: <503> but was: <200>
> CxfRsConsumerSuspendTest.testGracefulStopCompletesInflightAndRejectsNewRequests
> (asynchronous request in flight):
> A request received while stopping must be rejected ==> expected: <503> but
> was: <200>
> {noformat}
> With the fix the rejected requests get HTTP 503, request A (asynchronous, its
> continuation resumes after the suspend) still gets its response, and the
> route stops. No sleeps: latches, Awaitility.
> The defect was found with a TLA+ model of the consumer under a graceful
> shutdown / route suspend, with synchronous and asynchronous (continuation)
> requests: "a suspended consumer takes no new work" is violated in 3 steps
> (suspend, a request arrives, it is admitted). The property of CAMEL-12870,
> "the consumer is only stopped when nothing is inflight", holds on the current
> code and with the fix. A fix that also rejected resumed continuations would
> lose the responses of the requests in flight (shown by the model: "an
> admitted request gets its response" violated), so the fix only rejects new
> invocations.
> h3. Proposed fix
> In both invokers, reject a new invocation (synchronous, or a continuation
> that {{isNew()}}) while the consumer {{isSuspendingOrSuspended()}}:
> {{CxfConsumer}} throws a {{Fault}} with status code 503 (CXF's
> {{PhaseInterceptorChain}} logs it at WARN with the stack trace, as it does
> for any undeclared fault, e.g. a route failure; making it quieter would need
> {{FaultMode.CHECKED_APPLICATION_FAULT}}, which also drives WS-Addressing,
> WS-RM and the management counters, so it is left as is), {{CxfRsInvoker}}
> returns a 503 {{Response}} (a {{WebApplicationException}} is logged at WARN
> with its stack trace by CXF's {{WebApplicationExceptionMapper}}, once per
> rejected request). {{CxfRsInvoker}} still skips the continuation lookup for a
> sub resource locator invocation (its sub resource method is checked next). A
> resumed continuation is always completed. CAMEL-12870 only added {{implements
> Suspendable}} (no discussion on the ticket); its purpose, completing the
> requests in flight, is kept.
> Upgrade guide note, as a {{====}} subsection of the existing {{===
> camel-cxf}} section (a suspended CXF consumer answers 503 to new requests).
> With the fix the new tests and the camel-cxf-soap (168, 2 skipped),
> camel-cxf-rest (51), camel-cxf-spring-soap (161, 3 skipped) and
> camel-cxf-spring-rest (111) suites pass.
> Affected: 4.14.x, 4.18.x and main (same code, GitHub contents API), since
> 2.21.3 / 2.22.2 / 2.23.0.
> Duplicate check (2026-10-04): JIRA "cxf" with 503 / "graceful shutdown" /
> suspended (CAMEL-12870 above; CAMEL-18528 SpringBus shutdown order;
> CAMEL-24179 continuation timeout race; none about new requests while
> suspended). GitHub pull requests "cxf suspend", "CxfRsInvoker": none about
> this; the open draft #22358 (CAMEL-20009, getOut replacement) changes other
> lines of {{CxfRsInvoker}} (imports, {{prepareExchange}}).
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)