JAX-RS ExceptionMapper抛出MessageBodyProviderNotFoundException

时间:2017-02-27 17:57:04

标签: jax-rs

使用JAX-RS,我已经成功实现了ExceptionMapper for Exceptions,它不需要比HTTP状态代码更复杂的响应,如下所示。

@Provider 
public class ISBNNotFoundManager implements ExceptionMapper<ISBNNotFoundException>{

  @Override
  public Response toResponse(ISBNNotFoundException exception) {
      return Response.status(NOT_FOUND).build();
  }
}

这可以按预期工作。

但是,当bean验证失败时,我想回复一些更有用的东西。以下代码段会导致MessageBodyProviderNotFoundException。

@Provider
public class ConstraintViolationExceptionMapper implements 
                     ExceptionMapper<ConstraintViolationException> {

  @Override
  @Produces(MediaType.APPLICATION_JSON)
  public Response toResponse(ConstraintViolationException exception) {

      final Map<String, String> errorResponse =
        exception.getConstraintViolations()
        .stream()
        .collect(
          Collectors.toMap(o -> o.getPropertyPath().toString(), o -> o.getMessage()));


      return Response.status(Response.Status.BAD_REQUEST).entity(errorResponse).build();
    }

}

当bean验证发生时,响应包括HTTP响应代码500,根本原因如下:

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException:
MessageBodyWriter not found for media type=application/json, 
type=class java.util.HashMap, genericType=class java.util.HashMap.

我尝试过的不起作用:

  • 在GenericEntity中包装地图就像这样。与上面相同的结果:

    new GenericEntity&gt;(errorResponse){}

我尝试过DID的工作:

  • 在自定义POJO DataIntegrityValidation中包装地图,如下所示:

    @XmlRootElement
    public class DataIntegrityValidation {
    
       private  Map<String, String> errorResponse = new HashMap<>();
    
       public Map<String, String> getErrorResponse() {
            return errorResponse;
       }
    
       public void setErrorResponse(Map<String, String> errorResponse) {
          this.errorResponse = errorResponse;
       }
    }
    

然后在toResponse方法中,我将地图包装在DataIntegrityValidation POJO中,并将其添加到响应对象中。

    DataIntegrityValidation dataIntegrityValidation = 
       new DataIntegrityValidation();
         dataIntegrityValidation.setErrorResponse(errorResponse);

    return
      Response.status(Response.Status.BAD_REQUEST)
      .entity(dataIntegrityValidation).build();

这给出了以下JSON:

{
  "errorResponse": {
    "entry": [
      {
        "key": "saveBook.arg0.description",
        "value": "size must be between 100 and 2147483647"
      },
      {
        "key": "saveBook.arg0.published",
        "value": "must be in the past"
      },
      {
        "key": "saveBook.arg0.link",
        "value": "must match \"^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$\""
      }
    ]
  }
}

我可以忍受这个,但我真的很想知道为什么它不能处理Map,即使它包含在Generic Entity中。

欢迎所有回复。

1 个答案:

答案 0 :(得分:1)

Map和GenericEntity的编组失败的原因是因为没有与它们相关联的JAXB定义。当你将地图包裹在用@XmlRootElement注释的POJO中时;它能够正确地编组它。