Custom ExceptionMapper for Jersey not working on invalid JSON input

I have the following resource that uses JSON to map POJOs.

@Path("example") public class ExampleResource { @POST @Consumes(MediaType.APPLICATION_JSON) public Response addThesis(MyObject myObject) { return Response.ok().entity("Test").build(); } } 

Here's the POJO class:

 public class MyObject { private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } } 

When I send a POST request with the body {"title": "Test title"} , everything works fine. Answer Test , as expected. However, when I change the request to {"titlee": "Test title"} , the server responds as follows:

Unrecognized field "titlee" (class com.my.package.MyObject) not marked as ignorant (one well-known property: "title"]) in [Source: org.glassfish.jersey.me ssage.internal.ReaderInterceptorExecutor$UnCloseableInputStream@ 6dc6a46a; row: 2, column: 11] (via the reference chain: com.my.package.MyObject ["titlee"])

Obviously, this is an exception, abandoned and returned by Jersey. How can I catch this exception and return a custom status code and message?

What I have tried so far is to implement my own ExceptionMapper:

 @Provider public class MyJsonExceptionMapper implements ExceptionMapper<JsonProcessingException> { public Response toResponse(JsonProcessingException e) { return Response.status(400).entity("JSON Processing Error").build(); } } 

Unfortunately, the answer remains the same. When I implement ExceptionMapper for a custom exception and throw the corresponding exception in the resource method, everything works fine. I assume this is due to the default ExceptionMapper for JsonProcessingException overriding my own. Then I tried to create a common mapper ("implements ExceptionMapper"), but again it fails.

I looked literally everywhere and tried a lot of things, including the ResourceConfig extension and registering my cartographer, but so far nothing has worked.

Additional information that may help reduce the problem: I use Grizzly2 as an HTTP server, which I deploy as a FAT JAR.

Part of the dependencies of my pom.xml looks like this:

 <dependencies> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.24</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-grizzly2-http</artifactId> <version>2.24</version> </dependency> </dependencies> 

Any advice is appreciated.

+7
json jackson jersey jax-rs
source share
3 answers

Ok, this is stupid and hack-ish, but worked for me:

register(JacksonJaxbJsonProvider.class);

This is due to the following β€œgood default behavior” at the Jackson function entry point:

if (!config.isRegistered(JacksonJaxbJsonProvider.class)) { // add the default Jackson exception mappers context.register(JsonParseExceptionMapper.class); context.register(JsonMappingExceptionMapper.class);

: (

But I would prefer an answer that fixes the problem "for real" - i.e. without pre-registering the components so that the function cannot configure them correctly ...

+5
source share

I also ran into this problem. If JacksonFeature registered, you can simply register JacksonJaxbJsonProvider as a workaround.


When JacksonFeature is on the way to classes, it automatically opens Jersey. Another way to fix this is to turn off automatic discovery by setting ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE to true . As a result of this, you will need to register other functions manually.


Alternatively, you can get rid of the jersey-media-json-jackson and use jackson-jaxrs-json-provider . With this, you get rid of JacksonFeature , and then you can register your own display engines.


One last option, and probably what seems to be the right solution (as indicated in the Kysil Ivan answer ), you can write your own exception display unit and then give it a high priority, e.g. 1 . If you use automatic detection, just comment it with @Provider and @Priority :

 @Provider @Priority(1) public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> { ... } 

If you manually register your provider, you can give the provider a binding priority :

 @ApplicationPath("/") public class MyResourceConfig extends ResourceConfig { public MyResourceConfig() { register(JsonParseExceptionMapper.class, 1); } } 

See more details.

+2
source share

We use JAX-RS on Wildfly to implement our web services and use the following to accomplish what you are trying to do with Glassfish Jersey. Perhaps it has similar features that you could look at. Our steps:

  • The service is a standalone EJB, uses an EJB interceptor to throw exceptions and fill out an object request with details
  • Deploy a PostProcessInterceptor that reads from the object with the request scope and modifies the response until the service returns. (This applies to JAX-RS)
0
source share

All Articles