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)

Reply via email to