2016-06-23 6 views
4

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

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

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

ответ

4

Я изучал и тестировал вашу проблему. Проблема заключается в том, что исключения выброшен из CxF перехватчиков избежать потока JAX-RS (see the answer команды CXF)

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

Но вы не можете вернуть собственный ответ от перехватчика или ответить на Fault к клиенту.

Обходной я нашел, чтобы достичь желаемого поведения состоит в замене ответа с пользовательским объектом, который может быть обработан вашим обычным методом invokation, как exceptionMapper См CXF/ JAX-RS : Return Custom response from interceptor

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

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

Надеется, что это помогает

0

Я полностью согласны с предыдущим ответом. Моя реализация выглядит следующим образом:

@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 потребляется и ответ за исключением строит. Я не могу избежать Mapper Exception, когда объявлен как поставщик через WebClient, поэтому я решил использовать его и повторно использовать Exception позже.

Смежные вопросы