How to override a built-in exception mapper in Jersey 2.23?
Jersey's built-in ValidationExceptionMapper is registered via ValidationFeature. Probably, replacing Jersey's ValidationFeature with your own version can do the trick. It can be done as follows.
Firstly, disable auto-discoverable ValidationFeature
property(ServerProperties.BV_FEATURE_DISABLE, true);
Next step is to register a clone of Jersey's validation feature
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;
}
}
In the clone, you should specify your new ExceptionMapper.
Finally, register your new Feature
register(ValidationFeatureClone.class)
UPDATE:
From Jersey 2.20 onwards, default ValidationExceptionMapper
can be overwritten using HK2 binding as shown below.
register(new AbstractBinder() {
@Override
protected void configure() {
bind(NewValidationExceptionMapper.class).to(ExceptionMapper.class)
.in(Singleton.class).ranked(10);
}
});
It really turned out to be a regression bug in Jersey, introduced in January 2015.
Bug is related with two Jersey's extensions: for Weld and bean validation.
Because without Weld container started, my custom ValidationExceptionMapper
mapper takes precedence over the built-in one provided by the jersey-bean-validation
module, so my goal is achieved.
I've filled a bug report under JERSEY-3153, later moved as the issue #3425.
To be honest, I'm never ever going to use Weld + Jersey again... I'm so tired with this combination. Through the last two years I've encountered around 10 bugs already. I'm really tired.
Anyway, I hope it will help somebody.
UPDATE: As @Justin Jose noticed in the comments below, there is also another workaround for the mentioned bug. We can use HK2 bindings, to override the problematic built-in mapper:
register(new AbstractBinder() {
@Override
protected void configure() {
bind(my.custom.ValidationExceptionMapper.class).to(ExceptionMapper.class)
.in(Singleton.class);
}
});