I made an ExceptionMapper
to catch and log all exceptions, like:
@Provider
public class CatchAllExceptionsMapper implements ExceptionMapper<Throwable> {
private static final Logger LOG = LoggerFactory.getLogger(CatchAllExceptionsMapper.class);
@Override
public Response toResponse(Throwable exception) {
LOG.error("Exception not catched!", exception);
return Response.serverError().build();
}
}
It catches the Exception
s my code throws, but if I send a Request with a JSON value that throws an IllegalStateException
at my object's creation, this ExceptionMapper
is ignored and I get a 400 Bad Request
Response.
Funny thing is this Response is not the traditional Tomcat HTML formatted Response, its just plain text. It say just:
Cannot construct instance of `com.example.vo.AutoValue_Customer$Builder`, problem: First name is null or empty. at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream); line: 14, column: 1]
I thought this might be something short-circuiting Jersey, but my @PreMatching
ContainerRequestFilter
is executed beforehand, so I really have no idea why the 400
Response is not the traditional HTML one from Tomcat.
Why is this happening? What can I do to catch this and return my own Response?
As stated by Paul Samsotha in the comments, JacksonFeature
from the jersey-media-json-jackson
package define some ExceptionMapper
s, like JsonMappingException
and JsonParseException
. The solution is to create our own, register them within the ResourceConfig
and register JacksonFeature
last, otherwise it won't work.
e.g.
@Provider
@Priority(1) // hack for overriding other implementations.
public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> {
@Override
public Response toResponse(JsonMappingException exception) {
return Response.status(Status.BAD_REQUEST).build();
}
}
@Provider
@Priority(1) // hack for overriding other implementations.
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
@Override
public Response toResponse(JsonParseException exception) {
return Response.status(Status.BAD_REQUEST).build();
}
}
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(CatchAllExceptionsMapper.class);
register(JsonMappingExceptionMapper.class);
register(JsonParseExceptionMapper.class);
register(JacksonFeature.class);
}
}