JAX-RS自定义ExceptionMapper不拦截RuntimeException
我想将底层 RuntimeExceptions
包装为自定义 json 格式,使 servlet 容器不会将堆栈跟踪转储到客户端。
我关注这个问题: JAX-RS (Jersey) 自定义异常XML 或 JSON 。 调用时:
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;
}
我错过了什么?
多谢 !
环境:JAX-RS,jersey-server 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>
但为什么 Jersey 似乎从不调用它?
I want to wrap underlaying RuntimeExceptions
to a custom json format , making the servlet container won't dump the stacktrace to client.
I follow this question : JAX-RS (Jersey) custom exception with XML or JSON .
When calling :
try {
doSomething(parameters);
}
catch(RuntimeException e) {
throw new MyCustomException(500 , e.getMessage() , Status.INTERNAL_SERVER_ERROR);
}
When I intentionally feed wrong parameters (and trigger RuntimeException
thrown by doSomething()
) , I didn't see MyCustomExceptionMapper
working. Instead , the servlet container dumps :
The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
api.MyCustomException: (underlaying msgs)
The MyCustomExceptionMapper
is indeed registered in the 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;
}
What did I miss ?
Thanks a lot !
Environment : JAX-RS , jersey-server 1.5
classes spec :
class MyCustomException extends RuntimeException
@Provider
class MyCustomExceptionMapper implements ExceptionMapper<MyCustomException>
updated :
I suspect that Application.getClasses()
is never called , so I add some println messages :
@Override
public Set<Class<?>> getClasses()
{
System.out.println("\n\n\n\n ApiConfig getClasses");
}
And in deed , it's never shown !
I am sure this ApiConfig is in the web.xml :
<context-param>
<param-name>javax.ws.rs.core.Application</param-name>
<param-value>destiny.web.api.ApiConfig</param-value>
</context-param>
But why it seems Jersey never calls it ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我找到了解决方案。
我所要做的就是用 Spring 的
@Repository
注释 MyCustomExceptionMapper。并删除 web.xml 中的部分(不需要)
因为 Spring 将查找所有 @Repository 并找到 @Provider ,并且 Jersey 将使用它。
I found the solution.
All I have to do is annotate MyCustomExceptionMapper with Spring's
@Repository
.And remove the section in web.xml (not needed)
Because Spring will lookup all @Repository and find a @Provider , and Jersey will make use of it.
我认为(根据我的实验)异常提供程序是通过精确的类匹配而不是继承匹配来查找的,因此处理 RuntimeException 的异常提供程序只会如果应用程序抛出原始 RuntimeException 则触发;您向我们展示的课程并非如此。我有一些关于如何解决这个问题的理论(例如,使用自定义过滤器处理程序,或者可能使用 AOP),但还没有最终结果。
关于你问题的后半部分,我只是不知道。我所知道的是 Apache CXF(我使用过的 JAX-RS 实现)在这方面存在一些缺陷,因此我坚持手动注册所有
@Provider
在应用程序的 Spring 配置中。我将其作为经验提供......I think (on the basis of my experiments) that exception providers are looked up by exact class match, rather than by inheritance match, so an exception provider that handles
RuntimeException
will only fire if the app throws a rawRuntimeException
; that's not the case with the class you've showed us. I have some theories about how to fix this (e.g., with a custom filter handler, or possibly some use of AOP) but nothing final yet.In relation to the second half of your question, I just don't know. What I do know is that Apache CXF (the JAX-RS implementation I've worked with) has/had some failings in this area, and that I thus stick to registering all my
@Provider
s by hand in the app's Spring config. I offer that as experience…您的 web.xml 中的参数名称不正确,因此该设置被忽略。
正确的参数名称是 javax.ws.rs.Application (不是您要扩展的类 javax.ws.rs.core.Application )。
参见示例:
docs.oracle.com/cd/E24329_01/web.1211/e24983/configure.htm#RESTF179
Your web.xml had an incorrect param-name in web.xml so that setting was being ignored.
The correct param name is javax.ws.rs.Application (not javax.ws.rs.core.Application which is the class you're extending).
See for example:
docs.oracle.com/cd/E24329_01/web.1211/e24983/configure.htm#RESTF179
您只需要在 web.xml 中配置 servlet。您不需要将 @Repository 添加到您的 ExceptionMapper 中。
部署应用程序后,您可以在日志文件中看到以下几行:
测试使用:
You just need to configure the servlet in web.xml. You don't need to add @Repository to your ExceptionMapper.
When the application is deploy you can see the following lines in log file:
Tested with:
我遇到了同样的问题,web.xml 中的更改,特别是标签中的更改解决了该问题。
只需确保包含异常和异常映射器类的包,而不仅仅是包含模型和资源的包
jersey.config.server.provider.packages
基础包
前任。如果模型/实体的包是 pkg.entity 并且例外是 pkg.exception 参数值(基本包)将为 pkg。如果 basepackage 设置为 pkg.entity 它不起作用......这就是我解决问题的方法。
I faced the same problem and the change in web.xml, in particular in tag solved the issue.
Just make sure that the for the includes your package for the exception and exception mapper classes not only the packages containing the models and resources
jersey.config.server.provider.packages
basepackage
ex. if package for models/entities is pkg.entity and for exception is pkg.exception param-value (basepackage) will be pkg. If basepackage is set pkg.entity it doesn't work...that is how i solved the issue.