Jersey JAX-RS自定义异常Apper未截获运行时异常

Jersey JAX-RS自定义异常Apper未截获运行时异常,jersey,jax-rs,Jersey,Jax Rs,我想将底层RuntimeExceptions包装为自定义json格式,使servlet容器不会将stacktrace转储到客户端 我遵循这个问题:。 打电话时: try { doSomething(parameters); } catch(RuntimeException e) { throw new MyCustomException(500 , e.getMessage() , Status.INTERNAL_SERVER_ERROR); } 当我故意输入错误的参数(并触发doSo

我想将底层
RuntimeExceptions
包装为自定义json格式,使servlet容器不会将stacktrace转储到客户端

我遵循这个问题:。 打电话时:

try {
  doSomething(parameters);
}
catch(RuntimeException e) {
  throw new MyCustomException(500 , e.getMessage() , Status.INTERNAL_SERVER_ERROR);
}
当我故意输入错误的参数(并触发
doSomething()
引发的
RuntimeException
)时,我没有看到
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;
  }
事实上,它从未展示过

我确信此ApiConfig位于web.xml中:

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

javax.ws.rs.core.Application
destiny.web.api.ApiConfig
但是为什么Jersey似乎从不调用它呢?

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

关于你问题的后半部分,我只是不知道。我所知道的是,ApacheCXF(我使用过的JAX-RS实现)在这方面有一些缺陷,因此我坚持手工在应用程序的Spring配置中注册我所有的
@Provider
。我提供的经验…

我找到了解决方案

我所要做的就是用Spring的
@存储库
注释MyCustomExceptionMapper

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


javax.ws.rs.core.Application
destiny.web.api.ApiConfig

因为Spring将查找所有@Repository并找到@Provider,Jersey将使用它。

您只需要在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>
通过以下方式进行测试:

  • 泽西岛v1.11 2011年9月12日上午10:27
  • Spring v3.1.1
  • GlassFish服务器开源版本3.1.2(构建23)

您的web.xml在web.xml中有一个不正确的参数名,因此该设置被忽略

正确的参数名是javax.ws.rs.Application(不是您要扩展的类javax.ws.rs.core.Application)

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

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


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

“当选择异常映射提供程序来映射异常时,实现必须使用其泛型类型为最接近异常超类的提供程序。”@James您会认为这些事情总是正确实现的,不是吗?我也会这样做,除非经验告诉我不是这样(我想我正在考虑的实现非常喜欢使用
HashMap
s进行处理)。你唯一可以信赖的就是精确匹配。我同意软件总是有缺陷的。我们应该知道一旦遇到bug报告,如何创建bug报告。我正在当前项目中使用此功能。直到现在,一切都很顺利。为什么是@Repository?我想你的意思是应该用@Component注释它(就像所有其他资源一样)。我必须用
javax.ws.rs.ext.Provider
注释我的。使用jersey 1.x
  <context-param>
    <param-name>javax.ws.rs.core.Application</param-name>
    <param-value>destiny.web.api.ApiConfig</param-value>
  </context-param>
  <context-param>
    <param-name>javax.ws.rs.core.Application</param-name>
    <param-value>destiny.web.api.ApiConfig</param-value>
  </context-param>
<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