13
@Provider
public class JerseyExceptionMapper implements ExceptionMapper<JerseyException> {


    @Override
    public Response toResponse(JerseyException jerseyException) {
        return Response.status(jerseyException.getErrorCode()).
                entity(jerseyException.getJsonResponseObj()).
                type(MediaType.APPLICATION_JSON).
                build();
    }

}

The code above has unwanted results when you're using an <error-page> component in the web.xml. For example, if my Response.status is set to 400 and my error-page component defines an <error-code> of 400, the web server will redirect the request to the location defined in the web.xml.

This is obviously not what I want for REST requests. I read another post on StackOverflow that said the reason a request gets diverted to the error-page is because HttpServletResponse.sendError(400) is set. That post said if you set HttpServletResponse.setStatus(400) instead, the error-page will be ignored.

If that is true, I don't see how it's helpful since I did not implement the Jersey code. The option I'm seeing is to investigate the Response class source code and possibly re-implement the status method or perhaps other Jersey code. Is there a simple option here or something I'm missing?

Essentially, my question is: Given that I'm using Jersey for REST and I'm using error-page in my web.xml, how can I use the above code while ignoring the error-page for Jersey code only? Any other code that causes HTTP errors should go to the error-page. Or is there another solution that doesn't involve error-page but will work identical to what I want?

KyleM
  • 4,445
  • 9
  • 46
  • 78
  • Which servlet container are you using? this might be related to https://java.net/jira/browse/JERSEY-2673 – Dror Bereznitsky Dec 30 '14 at 20:10
  • I Could not reproduce this problem (glassfish 4 jersey 2.13). 1) What is `JerseyException`? 2) Have you checked to see if the mapper is called? 3) To make this work, I simply made a `JerseyException` class extend `WebApplicationException` and threw it from a resource method. 4) If the 3. doesn't make it work for you, can you please provide more information to reproduce this, like environment, Jersey version, Server, where the exception is being thrown. – Paul Samsotha Jan 01 '15 at 06:14

1 Answers1

6

I can reproduce the problem, but only if I pass a null as entity content.

Example:

return Response.status(400)
        .entity(null)
        .type(MediaType.APPLICATION_JSON)
        .build();

or even

return Response.status(400)
        .type(MediaType.APPLICATION_JSON)
        .build();

Both will result in a redirect to the error-page which is set up for HTTP status code 400 because the container will use the sendError() method if no message content is specified.

But if you do it like this:

return Response.status(400)
        .entity("An error occured.")
        .type(MediaType.APPLICATION_JSON)
        .build();

or this:

return Response.status(400)
        .entity("")
        .type(MediaType.APPLICATION_JSON)
        .build();

the container/jersey will only use the setStatus() method and won't redirect to the error-page. As stated in the docs:

This method is used to set the return status code when there is no error (for example, for the SC_OK or SC_MOVED_TEMPORARILY status codes).

If this method is used to set an error code, then the container's error page mechanism will not be triggered. If there is an error and the caller wishes to invoke an error page defined in the web application, then sendError(int, java.lang.String) must be used instead.

So in your case the problem seems to be that jerseyException.getJsonResponseObj() returns null. You should implement a null-check to avoid this.

There is bug JERSEY-1557 for Jersey 1.x which describes the problem, it was closed without a fix but with the advice to use an empty entity string as a workaround.
There is also a similar bug open for Jersey 2.x: JERSEY-2673

See also:

Community
  • 1
  • 1
unwichtich
  • 13,712
  • 4
  • 53
  • 66
  • I'm going to give you the bounty because you gave good information. However, I think what happened in my case (which you had no way of knowing) is an Exception was thrown by the entity() method because there was no MessageBodyWriter found. That exception must have caused the errorCode method to be called. Once I included genson JARs in my project, I do not get these errors anymore. – KyleM Jan 05 '15 at 17:47
  • This is exactly what I need. This error handling is not mentioned in Jersey's official documentation. – Srini Karthikeyan Jun 15 '20 at 13:54