Распространение исключения из перехватчика CXF в модуль отображения исключений

У меня есть поток, где на клиенте CXF у меня есть jaxrs-in-interceptor, поставщик и преобразователь исключений. В моем случае я ловлю плохой ответ от клиента через in-interceptor, а затем я хотел бы прервать цепочку шины cxf и выдать ошибку. К сожалению, я не смог этого сделать, потому что в каждой ситуации исключение, сгенерированное из перехватчика, только регистрируется, но основная ошибка (неправильный формат json) передается в преобразователь исключений. Я хотел бы избежать Exception Mapper, но я не знаю как. Я использую WebClient для реализации перехватчиков, как это:

@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-фильтр, потому что исключения, генерируемые перехватчиком, не распространяются на модуль отображения исключений. Есть ли способ сделать это в Java благодаря реализации WebClient?

S client = create(url, clazz, list(jsonProvider(), providers));
WebClient.getConfig(client).getInInterceptors().add(new MyInterceptor());

Я также пытался использовать разные фазы на перехватчике, но это также не сработало.

Ответы на вопрос(2)

Решение Вопроса

что исключения, генерируемые перехватчиками CXF, избегают потока JAX-RS (увидеть ответ команды CXF)

A Fault сгенерированный из перехватчика может быть пойман реализацииhandleFault в самом перехватчике

 public void handleFault(Message message) {
       Exception e = message.getContent(Exception.class);
 }

Или реализуяFaultListener и регистрация его в автобусе CXF

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 See.CXF / JAX-RS: вернуть пользовательский ответ от перехватчика

ВInterceptor.handleMessage проверьте необходимые условия и создайтеResponse с пользовательским статусом и сущностью. После этого остановите цепь

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

Добавьте ResponseExceptionMapper в качестве поставщика при создании клиента JAXRS

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 если выполнить проверку перехватчика. Вы можете поймать его или отбросить желаемым способом

try{
    proxy.yourService();
}catch (WebApplicationException e){
}

Надеюсь это поможет

 pedrofb27 мар. 2019 г., 14:25
@Robbo_UK, Ответ определяется JAX-RSjavax.ws.rs.core.Response учебный класс
 Robbo_UK27 мар. 2019 г., 14:17
пытался следовать этому, но javax.xml.ws.Response является интерфейсом. К какому пакету относится ответ?

@Component
public class ServiceFailureInterceptor extends AbstractPhaseInterceptor<Message> {

    private static final Logger LOG = LoggerFactory.getLogger(ServiceFailureInterceptor.class);

    public ServiceFailureInterceptor() {
        super(PRE_STREAM);
    }

    @Override
    public void handleMessage(Message message) {
        if (message != null) {
            int responseCode = (int) message.get(Message.RESPONSE_CODE);
                LogicException logicException = ErrorMapper.HTTP_STATUS_CODE_MAPPER.get(responseCode);
                InputStream is = b2stream(MapperUtils.json().toBytes(logicException));

                // clear old message & exchange
                Exchange exchange = message.getExchange();
                for (Class<?> contentFormat : message.getContentFormats()) {
                    message.setContent(contentFormat, null);
                }

                resetOrigInterceptorChain(message);
                resetFault(exchange);

                message.setContent(InputStream.class, is);
                Message outMessage = createOutMessage(exchange, is);
                prepareMessage(outMessage);
                prepareMessage(message);
        }
    }

    private void prepareMessage(Message message) {
        message.put(Message.REQUESTOR_ROLE, true);
        message.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
    }


    private Message createOutMessage(Exchange exchange, InputStream logicException) {
        Endpoint ep = exchange.get(Endpoint.class);
        Message outMessage = ep != null ? ep.getBinding().createMessage() : new MessageImpl();
        outMessage.setContent(InputStream.class, logicException);
        exchange.setOutMessage(outMessage);
        outMessage.setExchange(exchange);
        return outMessage;
    }

    private void resetFault(Exchange exchange) {
        exchange.put(Exception.class, null);
    }

    private void resetOrigInterceptorChain(Message message) {
        InterceptorChain chain = message.getInterceptorChain();
        if (chain != null) {
            for (Interceptor<?> interceptor : chain) {
                chain.remove(interceptor);
            }
            chain.reset();
        }
    }
}

После установки этого исключения вручную я перехожу к реализации ExceptionMapper, где используется мое LogicException и создается ответ с исключением. Я не могу избежать Exception mapper, когда он объявлен провайдером через WebClient, поэтому я решил использовать его и переназначить Exception позже.

Ваш ответ на вопрос