【问题标题】:Jersey ParamConverter exceptions not handled by ExceptionMapperJersey ParamConverter 异常未由 ExceptionMapper 处理
【发布时间】:2013-11-18 11:59:22
【问题描述】:

根据标题,从 ParamConverter 引发的异常未按我预期的方式处理。

使用 ExceptionMapper:

@Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {
    @Override
    public Response toResponse(MyException exception) {
        return Response.serverError().entity( "It triggered" ).build();
    }
}

和参数转换器:

@Provider 
(boilerplate junk)
    @Override
    public DateTime fromString(String value) {
        throw new MyException("convert");
    }

它不会在 500 错误中返回“它触发”文本,而是返回 404。

预期问题:两个提供商都注册了吗?

是的 - 如果我从资源中抛出“MyException”(在“常规”代码中),它会按预期工作。我还可以转换查看带有“转换”消息的堆栈跟踪。

有什么方法可以让来自 ParamConverters 的异常由 ExceptionMapper 处理?

我正在使用 jersey 2.3.1 以及 spring-jersey,在码头容器 9.1.0.RC0 中启动

【问题讨论】:

    标签: exception-handling jersey jax-rs jersey-2.0


    【解决方案1】:

    从阅读this 看来,JAX-RS 规范说实现者应该在NotFoundException (404) 中为@QueryParam@PathParam 包装未处理的异常,并且根据我测试的 400,(我'我猜测BadRequestException) 为@FormParam

    "如果字段或属性用@MatrixParam@QueryParam@PathParam 注释,则实现必须生成 NotFoundException(404状态)包装了抛出的异常,没有实体”

    我可以看到处理异常的几种方法是

    1. 只需在ParamConverter中处理即可,例如

      return new ParamConverter<T>() {
      
          @Override
          public T fromString(String string) {
              try {
                  return (T)new MyObject().setValue(string);
              } catch (MyException ex) {
                  Response response = Response.serverError().entity("Boo").build()
                  throw new WebApplicationException(response);
              }
          }
      
          @Override
          public String toString(T t) {
              return t.toString();
          }  
      };
      
    2. 或者只是让你的异常扩展WebApplicationException,并在那里返回Response。例如

      public class MyException extends WebApplicationException {
      
          public MyException(String message) {
              super(Response.serverError().entity(message).build());
          }
      }
      

    【讨论】:

    • 我必须说,我对这种行为感到非常惊讶,但最终它对我来说是有意义的。查询参数是 URL 的一部分,无法解析,URL 无效。我们在将日期 (YYYY-MM-DD) 解析为查询参数时遇到了问题。在我们的自定义查询参数转换器中,我们抛出了一个DateTImeParseException,实际上它随后被包装到了 NotFoundException 中。为了解决“问题”,我们现在抛出一个自定义异常,它使用自定义映射器从 WebApplicationException 继承。 :)
    【解决方案2】:

    我在 Jersey 2.26 中遇到了同样的行为。

    任何扩展 RuntimeException 的异常都会映射到 ParamException,它本身就是 WebApplicationException 的子类。 假设您的 MyException 扩展了 RuntimeException,它不会被捕获,因为您的 ExceptionMapper 只处理 MyException。

    关于 Jersey 文档说要抛出 NotFoundException:我认为 404 在无法转换 queryParam 时不适用。 BadRequestException 似乎更合适。而且,除了设置响应代码之外,当抛出 NotFoundException 时,我在 Jersey 框架中看不到任何独特之处

    要让从 ParamConverter 抛出的异常最终出现在 ExceptionMapper 中,您必须让 ExceptionMapper 捕获更全局的异常,例如 Throwable。

    另一个答案建议返回 WebApplicationException。这应该是一个很好的解决方案,但如果 R​​esponse 对象有一个实体,它将不起作用。见这里:https://github.com/jersey/jersey/issues/3716

    【讨论】:

      猜你喜欢
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多