9

在我的一个项目中,我已经将 Jersey 从 version 升级2.142.23. 但我在一个问题上苦苦挣扎了好几个小时。我的项目为 a 定义了自己ExceptionMapperValidationException,但不幸的是,Jersey 已经为此异常提供了一个内置的异常映射器,我无法覆盖它。

我已经正确注册(我检查了)我自己的映射器,如下所示:

@Provider
public class ValidationExceptionMapper implements 
         ExceptionMapper<ValidationException> {

    @Override
    public Response toResponse(ValidationException exception) {
        return Response.status(Status.BAD_REQUEST).build();
    }
}

但它永远不会被调用。泽西总是捡来的org.glassfish.jersey.server.validation.internal.ValidationExceptionMapper。我也尝试 @Priority为我的自定义映射器使用注释,但不幸的是 Jersey 没有考虑到它。

那么发生了什么?它在以前的 Jersey 版本中工作得非常好,所以它似乎是一个回归错误。

我放弃。有什么线索吗?

4

4 回答 4

6

事实证明,这实际上是 2015 年 1 月引入的 Jersey 中的回归错误。

错误与 Jersey 的两个扩展有关:焊接和 bean 验证。因为没有 Weld 容器启动,我的自定义ValidationExceptionMapper映射器优先于模块提供的内置映射器jersey-bean-validation,所以我的目标实现了。

我在JERSEY-3153下填写了一个错误报告,后来作为问题 #3425移动。

老实说,我再也不会使用 Weld + Jersey 了……我已经厌倦了这种组合。在过去的两年中,我已经遇到了大约 10 个错误。我真的累了。

无论如何,我希望它会对某人有所帮助。

更新:正如@Justin Jose 在下面的评论中注意到的那样,对于提到的错误还有另一种解决方法。我们可以使用 HK2 绑定来覆盖有问题的内置映射器:

register(new AbstractBinder() {
    @Override
    protected void configure() {
        bind(my.custom.ValidationExceptionMapper.class).to(ExceptionMapper.class)
               .in(Singleton.class);
    }
});
于 2016-08-11T13:59:42.587 回答
4

Jersey 内置的 ValidationExceptionMapper 是通过 ValidationFeature 注册的。也许,用您自己的版本替换 Jersey 的 ValidationFeature 可以解决问题。可以按如下方式完成。

首先,禁用自动发现的 ValidationFeature

property(ServerProperties.BV_FEATURE_DISABLE, true);

下一步是注册 Jersey 验证功能的克隆

public static class ValidationFeatureClone implements Feature {

    @Override
    public boolean configure(FeatureContext context) {
        context.register(new ValidationBinder());
        context.register(NewValidationExceptionMapper.class);
        context.register(ValidationErrorMessageBodyWriter.class);
        return true;
    }
}

在克隆中,您应该指定新的 ExceptionMapper。

最后,注册您的新功能

register(ValidationFeatureClone.class)

更新:

从 Jersey 2.20 开始,ValidationExceptionMapper可以使用 HK2 绑定覆盖默认值,如下所示。

register(new AbstractBinder() {
    @Override
    protected void configure() {

       bind(NewValidationExceptionMapper.class).to(ExceptionMapper.class)
           .in(Singleton.class).ranked(10‌​);
    }
});
于 2017-03-02T10:46:54.673 回答
0

我找到了一种让它再次与较新的 Jersey 版本一起工作的方法,我也在你的错误报告下发布了它。

需要使用更改后的代码(特别是jersey-bean-validation工件)在本地构建 Jersey。

在 中找到org.glassfish.jersey.server.validation.internal.ValidationBinder并注释掉以下两行configure()

bind(ValidationExceptionMapper.class).to(ExceptionMapper.class).in(Singleton.class);
bind(ValidationErrorMessageBodyWriter.class).to(MessageBodyWriter.class).in(Singleton.class);

具有讽刺意味的是,这些行上方的源代码注释说它们应该允许用户注册自己的提供程序。

于 2017-02-24T18:20:13.370 回答
0

不幸的是,该错误仍然存​​在并引起头痛......在我的情况下,最简单的解决方案是专门为 ConstraintViolationException 提供自定义 ExceptionMapper。

public class CVExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
   @Override
   public Response toResponse(final Throwable t) {
   ...
   }
}

然后像往常一样注册它: context.register(CVExceptionMapper.class);

于 2022-01-20T16:21:25.113 回答