2016-06-23 1 views
4

CXF 클라이언트에서 jaxrs-in-interceptor, provider 및 exception mapper가있는 곳에서 플로우가 발생했습니다. 내 경우에는 인 - 인터셉터를 통해 클라이언트로부터 잘못된 응답을 얻었고 cxf 버스 체인을 중단하고 오류를 던지 싶습니다. 불행하게도 나는 인터셉터에서 던져진 모든 상황 예외가 기록되지만, 메인 오류 (틀린 json 형식)가 예외 매퍼로 전파된다. 예외 매퍼 (Exception mapper)는 피하고 싶지만 어떻게해야할지 모르겠다. 나는이 같은 인터셉터를 구현하는 웹 클라이언트를 사용하고 있습니다 : 나는 예외 매퍼에 전파되지 않습니다 인터셉터에 의해 슬로우 jaxrs 필터 원인 예외를 구현해야한다는 읽어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()); 
      } 
     } 

. WebClient 구현 덕분에 Java에서 그렇게 할 수 있습니까?

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

나는 또한 인터셉터에서 다른 단계를 사용하려고 시도했지만 작동하지 않았습니다.

답변

4

귀하의 문제를 조사하고 테스트했습니다. 문제는 CXF 인터셉터에서 던진 예외가 (CXF 팀의 see the answer)를 JAX-RS 흐름

을 탈출하는 것이 인 인터셉터에서 생성 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; 
    } 
} 

에 그것을 등록하지만 당신은 인터셉터에서 사용자 지정 응답을 반환하거나 오류를 응답 할 수 없습니다 고객에게.

내가 원하는 동작을 달성하기 위해 찾은 해결 방법은 exceptionMapper 같은 조건 Interceptor.handleMessage 체크 속으로 CXF/ JAX-RS : Return Custom response from interceptor

을 참조하여 일반적인 방법 invokation에 의해 처리 될 수있는 사용자 지정 개체로 응답 교체에 구성하면 사용자 지정 상태 및 엔터티가 포함 된 Response이 필요합니다. 이 후, 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()); 

을 만들 때 공급자로 ResponseExceptionMapper 추가 체인

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

를 중지 proxy.yourService()에 대한 호출은 WebApplicationException acomplish 인터셉터 체크하는 경우를 올릴 것이다. 당신은 그것을 잡거나 원하는 방법으로 다시 발생 할 수

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

희망이

0

내가 완전히 이전의 대답에 동의하는 데 도움이됩니다. 내 LogicException가 소비되고 제외하고 응답이 구축된다

@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 구현에 갈거야 : 같은 내 구현 보인다. WebClient를 통해 공급자로 선언 될 때 Exception mapper를 피할 수 없으므로 나중에 사용하기로 결정하고 예외를 다시 매핑했습니다.

관련 문제