【问题标题】:JAX-RS ExceptionMapper throws MessageBodyProviderNotFoundExceptionJAX-RS ExceptionMapper 抛出 MessageBodyProviderNotFoundException
【发布时间】:2017-07-18 11:17:53
【问题描述】:

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

@Provider 
public class ISBNNotFoundManager implements ExceptionMapper<ISBNNotFoundException>{

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

这按预期工作。

但是,当 bean 验证失败时,我想用更有用的东西来响应。以下代码 sn-p 导致 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 中。结果和上面一样:

    新的 GenericEntity>(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 \\.-]*)*\\/?$\""
      }
    ]
  }
}

我可以忍受这个,但我真的很想知道为什么它不能处理地图,即使它被包装在通用实体中。

欢迎所有回复。

【问题讨论】:

    标签: jax-rs


    【解决方案1】:

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

    【讨论】:

    • 现在你向我解释一下就很有意义了。干杯。
    猜你喜欢
    • 2014-01-24
    • 1970-01-01
    • 2011-03-16
    • 2011-08-12
    • 2023-03-11
    • 1970-01-01
    • 2016-03-01
    • 2019-04-03
    • 1970-01-01
    相关资源
    最近更新 更多