JAX-RS自定义ExceptionMapper不拦截RuntimeException

时间:2011-04-25 04:18:34

标签: jersey jax-rs

我希望将RuntimeExceptions置于自定义json格式下,使servlet容器不会将堆栈跟踪转储到客户端。

我关注这个问题:JAX-RS (Jersey) custom exception with XML or JSON。 致电:

try {
  doSomething(parameters);
}
catch(RuntimeException e) {
  throw new MyCustomException(500 , e.getMessage() , Status.INTERNAL_SERVER_ERROR);
}

当我故意提供错误的参数(并触发RuntimeException引发的doSomething())时,我没有看到MyCustomExceptionMapper正常工作。相反,servlet容器转储:

The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
api.MyCustomException: (underlaying msgs)

MyCustomExceptionMapper确实在javax.ws.rs.core.Application

中注册
  @Override
  public Set<Class<?>> getClasses()
  {
    Set<Class<?>> set = new HashSet<Class<?>>();
    set.add(other classes);
    set.add(MyCustomExceptionMapper.class);
    return set;
  }

我错过了什么?

非常感谢!

环境:JAX-RS,泽西服务器1.5

类规范:

class MyCustomException extends RuntimeException 
@Provider
class MyCustomExceptionMapper implements ExceptionMapper<MyCustomException>

已更新

我怀疑永远不会调用Application.getClasses(),所以我添加了一些println消息:

  @Override
  public Set<Class<?>> getClasses()
  {
    System.out.println("\n\n\n\n ApiConfig getClasses");
  }

在行动中,它永远不会显示出来!

我确信这个ApiConfig位于web.xml中:

  <context-param>
    <param-name>javax.ws.rs.core.Application</param-name>
    <param-value>destiny.web.api.ApiConfig</param-value>
  </context-param>

但为什么泽西岛似乎从不称呼它呢?

5 个答案:

答案 0 :(得分:2)

我找到了解决方案。

我所要做的就是用Spring @Repository注释MyCustomExceptionMapper。

删除web.xml中的部分(不需要)

  <context-param>
    <param-name>javax.ws.rs.core.Application</param-name>
    <param-value>destiny.web.api.ApiConfig</param-value>
  </context-param>

因为Spring会查找所有的@Repository并找到一个@Provider,而Jersey会使用它。

答案 1 :(得分:1)

认为(根据我的实验)异常提供程序是通过精确的类匹配而不是通过继承匹配来查找的,因此处理RuntimeException的异常提供程序只会如果应用程序抛出原始RuntimeException,则触发;你向我们展示的课程并非如此。我有一些关于如何解决这个问题的理论(例如,使用自定义过滤器处理程序,或者可能使用AOP)但最终还没有。

关于你问题的后半部分,我只是不知道。我所知道的是Apache CXF(我曾与之合作的JAX-RS实现)在这方面有一些失败,因此我坚持在应用程序的Spring中手动注册我的所有@Provider s配置。我提供经验......

答案 2 :(得分:1)

您的web.xml在web.xml中的param-name不正确,因此忽略了该设置。

正确的param名称是javax.ws.rs.Application(不是javax.ws.rs.core.Application,它是你要扩展的类)。

参见例如: docs.oracle.com/cd/E24329_01/web.1211/e24983/configure.htm#RESTF179

答案 3 :(得分:0)

您只需要在web.xml中配置servlet。您不需要将@Repository添加到ExceptionMapper。

<servlet>
    <servlet-name>rest-servlet</servlet-name>
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>your.base.package.to.rest</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>rest-servlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

部署应用程序时,您可以在日志文件中看到以下行:

INFO: Scanning for root resource and provider classes in the packages:
your.base.package.to.rest

INFO: Root resource classes found:
class your.base.package.to.rest.resources.FooResource

INFO: Provider classes found:
class your.base.package.to.rest.providers.NotFoundMapper

经过测试:

  • Jersey v1.11 12/09/2011 10:27 AM
  • Spring v3.1.1
  • GlassFish Server开源版3.1.2(版本23)

答案 4 :(得分:0)

我遇到了同样的问题,web.xml中的更改,特别是在标签中解决了问题。 只需确保包含异常和异常映射器类的包不仅包含模型和资源的包              jersey.config.server.provider.packages         basepackage     

离。如果模型/实体的包是pkg.entity,而异常是pkg.exception,则param-value(basepackage)将是pkg。如果将basepackage设置为pkg.entity,它就不起作用......这就是我解决问题的方法。