9

REST 呼び出し中に例外が発生した場合、カスタム エラー コードとエラー メッセージを返す必要があります。例外マッパー プロバイダーを作成しました。これは、アプリケーション コードからの例外に対して適切に機能します。ただし、CXF コード (たとえば、私が作成した CustomValidationInterceptor など) から例外が発生した場合は機能しません。

たとえば、無効なパス パラメータ (無効な 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;
    }

}
4

2 に答える 2

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);
        }
    }
于 2013-06-14T03:40:32.317 に答える
2

cxf ユーザー グループで同様の質問をしました。以下を参照してください。

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

最終的にインターセプターを ContainerRequestFilter と ContainerResponseFilter に置き換えたところ、例外マッパーはアプリケーション例外とフィルターからスローされた例外の両方を問題なく処理しました。

お役に立てれば。

于 2013-09-19T19:53:59.507 に答える