Federico Mariani created CAMEL-24176:
----------------------------------------
Summary: camel-cxfrs - async producer never maps HTTP errors to
CxfOperationException (getClass().isInstance always false)
Key: CAMEL-24176
URL: https://issues.apache.org/jira/browse/CAMEL-24176
Project: Camel
Issue Type: Bug
Components: camel-cxfrs
Reporter: Federico Mariani
Assignee: Federico Mariani
*Severity:* High *[reproducer attached]*
h3. Problem
In the asynchronous cxfrs producer callbacks {{CxfInvocationCallback.fail(..)}}
and {{CxfProxyInvocationCallback.fail(..)}} the check for a JAX-RS error
response is:
{code:java}
if (throwable.getClass().isInstance(WebApplicationException.class)) {
...
} else if (throwable.getClass().isInstance(ResponseProcessingException.class)) {
...
} else {
exchange.setException(throwable);
}
{code}
{{x.getClass().isInstance(y)}} tests whether the *argument* {{y}} is an
instance of {{x}}'s class. Here the argument is the {{Class}} object
{{WebApplicationException.class}} (a {{java.lang.Class}}), which is never an
instance of any {{Throwable}}. *Both branches are dead code* and every async
failure falls through to {{exchange.setException(throwable)}} with the raw
JAX-RS exception.
h3. Impact
With the default {{synchronous=false}}, a server error (404/500...) yields the
raw {{NotFoundException}}/{{InternalServerErrorException}} instead of the
{{CxfOperationException}} (carrying status code, response headers and body)
that the *synchronous* path produces via {{populateCxfRsProducerException}}.
Any {{onException(CxfOperationException.class)}} handler that works with
{{synchronous=true}} silently stops matching when the route runs async.
h3. Location
{{components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java}}
lines ~751, 757 ({{CxfInvocationCallback}}) and ~844, 850
({{CxfProxyInvocationCallback}}).
h3. Fix
Use {{instanceof}}:
{code:java}
if (throwable instanceof WebApplicationException wae) {
if (shouldHandleError(wae.getResponse())) { handleError(wae.getResponse());
}
else { exchange.setException(throwable); }
} else if (throwable instanceof ResponseProcessingException rpe) {
...
} else {
exchange.setException(throwable);
}
{code}
Ensure the fixed branch still falls back to
{{exchange.setException(throwable)}} when {{shouldHandleError}} returns false,
so a non-handled exception isn't dropped. The two {{InvocationCallback}} inner
classes duplicate this logic verbatim - de-duplicate them so the fix cannot
regress in one copy.
h3. Reproducer
{{CxfRsProducerAsyncExceptionPredicateReproducerTest}} (attached) pins the
defective predicate against a real {{WebApplicationException}} subclass and
fails on current {{main}}.
----
_Filed by Claude Code (Claude Fable) on behalf of Federico Mariani (GitHub:
Croway). Findings from an AI-assisted code review of the camel-cxf component
family; each item was verified against the current source and git history.
Items marked *[reproducer attached]* include a failing JUnit test that
demonstrates the defect._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)