I've a flow where on CXF client I've jaxrs-in-interceptor, provider and exception mapper. In my case I'm catching bad response from client through in-interceptor and then I would like abort the cxf bus chain and throw a fault. Unfortunately I couldn't do it, cause in every situation exception thrown from interceptor is being only logged, but the main error (wrong json format) is propagated to exception mapper. I would like to avoid Exception mapper, but I don't know how. I'm using WebClient to implement interceptors like this:
@Component
public class MyInterceptor extends AbstractPhaseInterceptor<Message> {
public MyInterceptor() {
super(POST_STREAM);
}
@Override
public void handleMessage(Message message) throws Fault {
if (message != null) {
//message.getExchange().setOneWay(true);
//message.getExchange().put(Exception.class, new MyException());
//message.getInterceptorChain().abort();
//message.setContent(Exception.class, new MyException());
//Endpoint ep = message.getExchange().get(Endpoint.class);
//message.getInterceptorChain().abort();
//if (ep.getInFaultObserver() != null) {
// ep.getInFaultObserver().onMessage(message);
//}
//throw new WebApplicationException( new MyException());
//message.setContent(Response.class, response);
throw new Fault(new MyException());
}
}
I read that I should implement jaxrs-filter cause exceptions thrown by interceptor are not propagated to exception mapper. Is it any way to do that in java thanks to WebClient implementation?
S client = create(url, clazz, list(jsonProvider(), providers));
WebClient.getConfig(client).getInInterceptors().add(new MyInterceptor());
I've also tried to use different phases on interceptor, but it also didn't work.
I have been researching and testing with your issue. The problem is that the exceptions thrown from the CXF interceptors escape the JAX-RS flow (see the answer of CXF team)
A Fault
generated from interceptor can be catched implementing handleFault
in the interceptor itself
public void handleFault(Message message) {
Exception e = message.getContent(Exception.class);
}
Or implementing a FaultListener
and registering it at CXF Bus
WebClient.getConfig(client).getBus().getProperties().put("org.apache.cxf.logging.FaultListener",new MyFaultListener());
public class MyFaultListener implements FaultListener{
public boolean faultOccurred(final Exception exception,final String description,final Message message) {
//return false to avoid warning of default CXF logging interceptor
return false;
}
}
But you can not return custom response from interceptor or respond a Fault to client.
The workaround I have found to achieve the desired behaviour consist in replacing the Response with a custom object that could be processed by your usual method invokation, like an exceptionMapper See CXF/ JAX-RS : Return Custom response from interceptor
Into Interceptor.handleMessage
check the conditions you need and create a Response
with custom status and entity. After this, stop the chain
public class MyInterceptor extends AbstractPhaseInterceptor<Message> {
public MyInterceptor() {
super(Phase.POST_STREAM);
}
@Override
public void handleMessage(Message message) throws Fault {
if (message != null) {
//check the condition to raise the error
//build the custom Response replacing service call
Response response = Response
.status(Response.Status.BAD_REQUEST)
.entity("custom error")
.build();
message.getExchange().put(Response.class, response);
//abort interceptor chain in you want to stop processing or throw a Fault (catched by handleFault)
//message.getInterceptorChain().abort();
//throw new Fault (new MyException());
}
public void handleFault(Message messageParam) {
}
}
Add the ResponseExceptionMapper as provider when creating the JAXRS client
providers.add(new ResponseExceptionMapper<WebApplicationException>() {
@Override
public WebApplicationException fromResponse(Response r) {
return new WebApplicationException(r);
}
});
YourService proxy = JAXRSClientFactory.create(url, clazz,providers);
Client client = WebClient.client(proxy);
WebClient.getConfig(client).getInInterceptors().add(new MyInterceptor());
After this, a call to proxy.yourService()
will raise a WebApplicationException
if acomplish the interceptor check. You can catch it or rethrow in the desired way
try{
proxy.yourService();
}catch (WebApplicationException e){
}
Hope this helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With