如何覆盖Jersey 2.23中的内置异常映射器?

时间:2016-07-31 08:05:33

标签: java jersey jersey-2.0 embedded-jetty weld2

在我的一个项目中,我已将Jersey从版本2.14升级到2.23。但是我遇到了一个问题需要花费很多时间。我的项目为ExceptionMapper定义了自己的ValidationException,但不幸的是,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版本中运行得非常好,所以它似乎是一个回归错误。

我放弃了。有线索吗?

3 个答案:

答案 0 :(得分:5)

在2015年1月推出的Jersey中,它确实是一个回归错误。

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

我已填写 JERSEY-3153 下的错误报告,后来移至issue #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);
    }
});

答案 1 :(得分:4)

Jersey的内置ValidationExceptionMapper是通过ValidationFeature注册的。也许用自己的版本替换泽西岛的ValidationFeature可以解决问题。它可以如下完成。

首先,禁用可自动发现的ValidationFeature

property(ServerProperties.BV_FEATURE_DISABLE, true);

下一步是注册泽西岛验证功能的克隆

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‌​);
    }
});

答案 2 :(得分:0)

我找到了一种方法让它再次与更新的泽西版本一起使用,我也在你的错误报告中发布了。

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

找到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);

具有讽刺意味的是,源代码评论高于这些线条表明他们应该允许用户注册他们自己的提供商。