2013-06-13 92 views
9

当REST调用期间发生异常时,我们需要返回自定义错误代码和错误消息。我们创建了一个异常映射器提供程序,它适用于应用程序代码中的异常。但是,当CXF代码发生异常时(例如,构成我写的CustomValidationInterceptor),它不起作用。CXF/JAX-RS:返回来自拦截器的自定义响应

例如,如果我请求无效的路径参数(例如无效的phoneNumber)。在这种情况下,我们需要以JSON格式返回自定义错误代码和错误消息,但即使我们创建了处理WebApplicationException的异常映射器提供程序,它也不起作用。

有没有办法处理来自cxf拦截器的异常,并返回 对用户的响应,如下所示?

{ 
"errorDetail": { 
"errorCode": "404", 
"errorMessage": "Bad Request" 
} 
} 
我CustomValidationInterceptor的

代码段:

public class CustomValidationInterceptor extends AbstractPhaseInterceptor<Message>{ 

    public CustomValidationInterceptor() { 
     super(Phase.PRE_INVOKE); // Put this interceptor in this phase 
    } 

    public void handleMessage(Message message) { 

     MetadataMap<String, String> metadataMap = (MetadataMap<String, String>) message.get("jaxrs.template.parameters"); 

     if(null != metadataMap) { 
      List<String> list = metadataMap.get("phoneNumber"); 
      if(null != list) { 
       String phoneNumber = list.get(0); 
       boolean result = validatePhoneNumber(phoneNumber); 
       if(!result){ 
        throw new TelusServiceException(Response.status(Response.Status.BAD_REQUEST).build(), 400, "phone number not valid"); 
       } 
      } else { 
       throw new TelusServiceException(Response.status(Response.Status.BAD_REQUEST).build(), 400, "phone number not valid"); 
      } 
     } else { 
      throw new TelusServiceException(Response.status(Response.Status.BAD_REQUEST).build(), 400, "phone number not valid"); 
     } 
    } 

    public boolean validatePhoneNumber(String phoneNumber) { 

      Pattern pattern = Pattern.compile("^[1-9]\\d{9}$"); 
      Matcher matcher = pattern.matcher(phoneNumber); 

      if (!matcher.matches()) { 
       return false; 
      } 
      return true; 
    } 

} 

代码我的自定义异常映射器提供

public class TelusExceptionHandler implements ExceptionMapper<TelusServiceException> { 

    public Response toResponse(TelusServiceException exception) { 
     return Response.status(exception.getErrorDetail().getErrorCode()).entity(exception.getErrorDetail()).build(); 
    } 

} 

代码TelusServiceException

public class TelusServiceException extends WebApplicationException{ 

// constructors and other methods 

    private ErrorDetail errorDetail = null; 

     public ErrorDetail getErrorDetail() { 
     return errorDetail; 
    } 

    public void setErrorDetail(ErrorDetail errorDetail) { 
     this.errorDetail = errorDetail; 
    } 

     public TelusServiceException(Response response, int errorCode, String errorMessage) { 
     super(response); 

     errorDetail = new ErrorDetail(); 
     errorDetail.setErrorCode(errorCode); 
     errorDetail.setErrorMessage(errorMessage); 
    } 

} 

代码片段的片段的片段ErrorDetail类

@XmlRootElement(name="errorDetail") 
public class ErrorDetail { 

    private int errorCode; 
    private String errorMessage; 

    @XmlElement(name = "errorCode") 
    public int getErrorCode() { 
     return errorCode; 
    } 

    public void setErrorCode(int errorCode) { 
     this.errorCode = errorCode; 
    } 
    @XmlElement(name = "errorMessage") 
    public String getErrorMessage() { 
     return errorMessage; 
    } 

    public void setErrorMessage(String errorMessage) { 
     this.errorMessage = errorMessage; 
    } 

} 
+0

我纠正了JSON。请参阅 – Bhuvan

+0

TelusServiceException的'.getErrorDetail()'的代码是什么? – fge

+0

添加了TelusServiceException和ErrorDetail对象的代码片段 – Bhuvan

回答

7

的我找到了一种方法来发送自拦截定制的响应,但仍然无法想出一个办法,以自拦截

代号叫我CustomExceptionHandler:

public void handleMessage(Message message) { 

     MetadataMap<String, String> metadataMap = (MetadataMap<String, String>) message.get("jaxrs.template.parameters"); 

     if(null != metadataMap) { 
      List<String> list = metadataMap.get("phoneNumber"); 
      if(null != list) { 
       String phoneNumber = list.get(0); 
       boolean result = validatePhoneNumber(phoneNumber); 
       if(!result){ 
// Create a response object and set it in the message. 
// calling getExchange() will not call your service 
        Response response = Response 
       .status(Response.Status.BAD_REQUEST) 
       .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString())) 
       .build(); 
     message.getExchange().put(Response.class, response); 
// That's it 
       } 
      } else { 
       Response response = Response 
       .status(Response.Status.BAD_REQUEST) 
       .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString())) 
       .build(); 
     message.getExchange().put(Response.class, response); 
      } 
     } else { 
      Response response = Response 
       .status(Response.Status.BAD_REQUEST) 
       .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString())) 
       .build(); 
     message.getExchange().put(Response.class, response); 
     } 
    } 
2

我提出的CXF用户组类似的问题,请参见:

http://cxf.547215.n5.nabble.com/Handling-exceptions-in-a-JAX-RS-fault-interceptor-when-using-Local-Transport-td5733958.html

我最终用ContainerRequestFilter和ContainerResponseFilter替换了拦截器,然后Exception Mapper很高兴地处理了从过滤器抛出的应用程序异常和异常。

希望这会有所帮助。

+0

也许你有一个类似的问题: http://stackoverflow.com/questions/37984617/avoid-exception-mapper-through-cxf-interceptor –

相关问题