代码之家  ›  专栏  ›  技术社区  ›  Alexander Rühl

JAX-RS异常映射器:打包的异常和默认情况如何?

  •  0
  • Alexander Rühl  · 技术社区  · 6 年前

    处理REST服务中异常的典型方法是定义自定义异常类型(通常来自 RuntimeException )然后实现映射器类以生成HTTP代码,例如:

    public class MyExceptionMapper implements ExceptionMapper<MyException> {
      @Override
      public Response toResponse(MyExceptionex) {
        return Response.status(400).entity("bad request")
          .type(MediaType.APPLICATION_JSON).build();
      }
    }
    

    现在,我有两个问题:

    • 我如何实现“默认情况”的映射器,这意味着没有映射到这里或其他映射器中的每个异常?例如,当为 Throwable 为了生成HTTP 500,它是否会再次捕获我自己的异常?或者可以定义一个映射器工作的顺序?
    • 当从REST服务调用EJB之类的托管组件时,在那里引发的异常不会导致 EJBException 或者一些 Transaction...Exception 把我自己的包起来?
    1 回复  |  直到 6 年前
        1
  •  3
  •   Nikos Paraskevopoulos    6 年前

    “默认情况”的映射器…

    正如PaulSamsotha在注释中所写,JAX-RS服务器运行时应该选择最具体的异常映射器。或者引用JAX-RS规范(对于JEE7/2.0版):

    3.3.4例外情况

    […]

    1. 如果异常映射提供程序(参见第4.4节)可用于异常或其某个超类,则实现必须使用其泛型类型是异常的最近超类的提供程序来创建响应实例,然后根据第3.3.3节处理该响应实例。…]

    所以我想您可以使用一个异常映射器 Throwable -它的签名验证了它:

    public interface ExceptionMapper<E extends Throwable> {...}
    

    从REST服务调用EJB等托管组件时…

    如果需要包装异常,EJB容器将包装它。并非所有EJB抛出的异常都需要包装。EJB规范(v3.1)区分了应用程序异常(注释为 javax.ejb.ApplicationException )以及“所有其他例外情况”(见第14.3节)。 那就破例吧 @ApplicationException 并提供一个映射器。但是如果你仍然想根据 包裹 例外:

    基于包装的异常响应

    不能基于包装的异常直接选择映射器。但是你 可以 为创建异常映射器 包装器 打开它并为 包裹 基于的异常 Providers 上下文(见JAX-RS 2.0第9.2.6节和 javax.ws.rs.ext.Providers JavaDoc)。一个例子,假设的未测试代码 MyWrapperException 将是:

    @Provider
    public class MyWrapperExceptionMapper implements ExceptionMapper<MyWrapperException> {
        @Context
        private Providers providers;
    
        public Response toResponse(MyWrapperException e) {
            Throwable t = e.getCause();
            ExceptionMapper mapper = providers.getExceptionMapper(t.getClass());
            if( mapper != null ) {
                return mapper.toResponse(t);
            }
            else {
                // custom handling...
            }
        }
    }