【问题标题】:Jersey unable to catch any Jackson Exception泽西岛无法捕捉到任何杰克逊异常
【发布时间】:2016-01-05 15:24:52
【问题描述】:

对于我的 REST api,我使用 jersey 和 ExceptionMapper 来捕获全局异常。 它适用于我的应用程序抛出的所有异常,但我无法捕获杰克逊抛出的异常。

例如,我的一个端点接受一个包含枚举的对象。如果请求中的 Json 具有不在枚举球衣中的值,则抛出此异常

Can not construct instance of my.package.MyEnum from String value 'HELLO': value not one of declared Enum instance names: [TEST, TEST2]
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@5922e236; line: 3, column: 1] (through reference chain: java.util.HashSet[0]->....)

即使我已经创建了这个映射器

@Provider
@Component
public class JacksonExceptionMapper implements ExceptionMapper<JsonMappingException> {
  @Override
  public Response toResponse(JsonMappingException e) {
    ....
  }
}

代码永远不会到达这个映射器。

为了捕获这些异常,我们需要做些什么吗?

编辑 注意:我只是尝试不那么通用,而不是 JsonMappingException 我使用 InvalidFormatException 在这种情况下调用映射器。但是我还是不明白,因为 InvalidFormatException 扩展了 JsonMappingException 并且也应该被调用

【问题讨论】:

  • 什么版本的杰克逊?
  • jersey-media-json-jackson (2.22.1) 但我也有 com.fasterxml.jackson.core jackson-annotations (2.6.3)
  • 杰克逊已经有一个mapper for this exception。这就是可能正在使用的东西。
  • 有趣的是,事实上异常发生在哪里......我真的不喜欢我的异常(包含所有名称和包名称)像这样被泄露,有什么办法可以覆盖它吗?
  • 我假设您正在注册JacksonFeature.class,所以泽西岛使用杰克逊。如果是这样的话,Jackson 正在注册它自己的映射器。您可以尝试注册JacksonJaxbJsonProvider.class,而不是注册它自己的异常映射器。这应该可以解决问题。

标签: json exception jersey jackson exceptionmapper


【解决方案1】:

遇到同样的问题。
问题是 JsonMappingExceptionMapper 在您的映射器之前启动。

实际的例外是 com.fasterxml.jackson.databind.exc.InvalidFormatException 类,映射器定义了 com.fasterxml .jackson.jaxrs.base.JsonMappingException,所以它更具体到异常。
你看,Jersey 的异常处理程序会寻找最准确的处理程序(参见 org.glassfish.jersey.internal.ExceptionMapperFactory#find(java.lang.Class, T))。

要覆盖此行为,只需禁用映射器即可:

  1. 使用 XML: <init-param> <param-name>jersey.config.server.disableAutoDiscovery</param-name> <param-value>true</param-value> </init-param>

  2. 使用代码:resourceConfig.property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true); 其中 resourceConfig 的类型为 org.glassfish.jersey.server.ServerConfig。


您也可以编写自己的特定映射器:

public class MyJsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException>

但我认为这是过度杀戮。

【讨论】:

  • 太感谢了!那个花了我太长时间的人。对于下一个可怜的灵魂 - 如果您使用提供者,您不必完全禁用发现,您可以使用 Priority 注释将优先级设置得更高。我只是选择了 1000 作为保存方,这将杰克逊提供的一个推到后面并改用我的。
【解决方案2】:

您好,现在似乎退出了不需要禁用 Jersey AUTO_DISCOVERY 功能的替代答案。

只需使用@Priority(1) 注释来注释您自己的异常映射器。数字越小,优先级越高。由于杰克逊自己的映射器没有任何优先注释,你的将被执行:

@Priority(1)
public class MyJsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException>

【讨论】:

  • 优先级和提供者标签对我不起作用。彼得的回答奏效了。这个虽然听起来更有效。任何线索为什么优先级可能会失败?
  • 您使用的是哪个球衣版本?我发现此问题已在球衣版本 2.29 github.com/eclipse-ee4j/jersey/issues/4099 中修复
【解决方案3】:

从版本 2.29.1 [1] 开始,如果您正在注册 JacksonFeature,您现在可以在不注册异常映射器 [2] 的情况下这样做:

register(JacksonFeature.withoutExceptionMappers());

[1]https://github.com/eclipse-ee4j/jersey/pull/4225

[2]https://eclipse-ee4j.github.io/jersey.github.io/apidocs/2.34/jersey/org/glassfish/jersey/jackson/JacksonFeature.html#withoutExceptionMappers--

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 2015-10-19
    • 2012-06-07
    相关资源
    最近更新 更多