Jersey unable to catch any Jackson Exception
Asked Answered
C

3

11

For my REST api I'm using jersey and ExceptionMapper to catch global exceptions. It works well all the exception my app throws but I'm unable to catch exception thrown by jackson.

For example one of my endpoint accept an object that contains an enum. If the Json in the request has a value that is not in the enum jersey throw this exception back

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]->....)

Even though I have created this mapper

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

The code never reach this mapper.

Is there anything we need to do in order to catch these exceptions?

EDIT Note: I have jus tried being less general and instead of JsonMappingException I use InvalidFormatException in this case the mapper is called. But I still don't understand because InvalidFormatException extends JsonMappingException and should be called as well

Cheyney answered 5/1, 2016 at 15:24 Comment(5)
What version of Jackson?Lcm
jersey-media-json-jackson (2.22.1) but I have com.fasterxml.jackson.core jackson-annotations (2.6.3) as wellCheyney
Jackson already has a mapper for this exception. That's what's probable being used.Zea
interesting that's infact where the exception goes... I don't really like my exception (with all the names and packages name) to be leaked like this is there any way I can override this ?Cheyney
I assume you're registering JacksonFeature.class so Jersey uses Jackson. If that's the case, Jackson is registering it's own mapper. You can try registering JacksonJaxbJsonProvider.class instead which doesn't register it's own exception mapper. That should do the trick.Sweetening
E
10

Had the same problem.
The problem is that JsonMappingExceptionMapper kicks in before your mapper.

The actual exception is of class com.fasterxml.jackson.databind.exc.InvalidFormatException and the mapper defines com.fasterxml.jackson.jaxrs.base.JsonMappingException, so it's more specific to the exception.
You see, Jersey's exception handler looks to find the most accurate handler (see org.glassfish.jersey.internal.ExceptionMapperFactory#find(java.lang.Class, T)).

To override this behavior, simply disable the mapper from being used:

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

  2. Using code: resourceConfig.property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true); where resourceConfig is of type org.glassfish.jersey.server.ServerConfig.


You can also write your own specific mapper:

public class MyJsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException>

But I think it's an over kill.

Erickericka answered 19/1, 2016 at 13:23 Comment(1)
GEEEEEE THANK YOU! Man that took me way too long. For the next poor soul - if you are using providers you don't have to disable the discovery completely, you can use a Priority annotation to set the priority higher. I just chose 1000 to be on the save side, that pushes the jackson provided one into the back and uses mine instead.Handsaw
T
6

Hi it seems to exits an alternative answer now that does not require to disable Jersey AUTO_DISCOVERY feature.

Just annotate your own exception mapper with a @Priority(1) annotation. The lower the number, the higher the priority. Since Jackson's own mappers do not have any priority annotation, yours will be executed:

@Priority(1)
public class MyJsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException>
Teodora answered 19/2, 2019 at 16:2 Comment(2)
The Priority along with the Provider tag do not work for me. Peter's answers worked. This one though sounds more valid. Any clue why the Priority might have failed?Conterminous
Which jersey version are you using? I found this issue fixed in jersey version 2.29 github.com/eclipse-ee4j/jersey/issues/4099Teodora
D
2

Starting in version 2.29.1 [1], if you're registering the JacksonFeature, you can now do so without registering the exception mappers [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--

Defaulter answered 28/10, 2021 at 16:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.