I have the following resource that consumes a JSON being mapped to a POJO.
@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. The response is Test, as expected. However, when I change the request to {"titlee":"Test title"} the server replies with this:
Unrecognized field "titlee" (class com.my.package.MyObject), not marked as ignorable (one known property: "title"]) at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@6dc6a46a; line: 2, column: 11] (through reference chain: com.my.package.MyObject["titlee"])
Obviously this is an exception thrown and returned by Jersey. How can I intercept this exception and return a custom status code and message?
What I've 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 response stays the same. When I implement an ExceptionMapper for a custom exception and throw the corresponding exception in the resource method though, everything works fine. I assume this has to do with the default ExceptionMapper for JsonProcessingException overriding my own one. Then I tried to create a generic mapper ("implements ExceptionMapper"), but again no success.
I've looked literally everywhere and tried many things including extending ResourceConfig and registering my mapper, but nothing has worked so far.
Some more information that might help to narrow the problem down: I am using Grizzly2 as the HTTP server which I am deploying as a Fat JAR.
The dependency part 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 highly appreciated.
Ok, this is dumb and hack-ish, but worked for me:
register(JacksonJaxbJsonProvider.class);
This is due to the following "nice default behavior" in the Jackson feature entry point:
if (!config.isRegistered(JacksonJaxbJsonProvider.class)) {
// add the default Jackson exception mappers
context.register(JsonParseExceptionMapper.class);
context.register(JsonMappingExceptionMapper.class);
:(
But, I'd still prefer an answer that fixes the problem "for real" - ie. without pre-registering components so that the feature cannot configure them properly...
I also faced this issue. If JacksonFeature
is registered, you can simply register JacksonJaxbJsonProvider
as a workaround.
When the JacksonFeature
is in the classpath, it is automatically discovered by Jersey. Another approach to fix it is disabling auto discovery by setting ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE
to true
. As a result of this, you would need to register other features manually.
Alternatively you can get rid of the jersey-media-json-jackson
artifact and use jackson-jaxrs-json-provider
instead. With this, you will get rid of JacksonFeature
and then you can register your own exception mappers.
One last option and probably what seems to be the correct solution (as pointed in Kysil Ivan's answer) you can write your own exception mapper and then give it a high priority, such as 1
. If you use auto discovery, just annotate it with @Provider
and @Priority
:
@Provider
@Priority(1)
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
...
}
If you manually register your provider, you can give your provider a binding priority:
@ApplicationPath("/")
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(JsonParseExceptionMapper.class, 1);
}
}
See this answer for more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With