shashank created CAMEL-25314:
--------------------------------
Summary: 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
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)