将CXF拦截器的异常传播到异常映射器 [英] Propagate exception from CXF interceptor to exception mapper

查看:671
本文介绍了将CXF拦截器的异常传播到异常映射器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个流程,在CXF客户端我有jaxrs-in-interceptor,提供者和异常映射器。在我的情况下,我通过拦截器捕获来自客户端的错误响应,然后我想中止cxf总线链并抛出错误。不幸的是我不能这样做,因为在每种情况下,拦截器抛出的异常只被记录,但是主要错误(错误的json格式)被传播到异常映射器。我想避免异常映射器,但我不知道如何。我正在使用WebClient来实现这样的拦截器:

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());
            }
        } 

我读到我应该实现jaxrs-filter导致异常拦截器抛出的不会传播到异常映射器。由于WebClient的实现,在java中是否可以这样做?

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.

推荐答案

我一直在研究和测试您的问题。问题是从CXF拦截器抛出的异常逃脱了JAX-RS流程(查看CXF团队的答案

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 <从拦截器生成的code> Fault 可以在拦截器本身中实现 handleFault

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);
 }

或实现 FaultListener 并在CXF总线上注册

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;
    }
}

但是你无法从中返回自定义回复拦截器或向客户端回应故障。

我发现实现所需行为的变通方法是将Response替换为可以处理的自定义对象通过常规方法调用,如exceptionMapper
请参阅 CXF / JAX-RS:从拦截器返回自定义响应

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

进入 Interceptor.handleMessage 检查您需要的条件并使用自定义状态和实体创建响应。在此之后,停止链

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) {
    }
}

在创建JAXRS客户端时添加ResponseExceptionMapper作为提供者

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());

此后,调用 proxy.yourService()将引发 WebApplicationException 。你可以按照理想的方式捕获它或重新抛出

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){
}

希望这有帮助

这篇关于将CXF拦截器的异常传播到异常映射器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆