Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignoring web.xml error-page with Jersey's ExceptionMapper

@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?

like image 584
KyleM Avatar asked Dec 26 '14 23:12

KyleM


People also ask

How to handle exceptions in Jersey?

In Jersey you have currently to possibilities to handle exceptions via mapping exceptions to responses via ExceptionMappers I like the second approach because it gives more control on the error entity I might send back.

How to handle custom exception in JAX-RS based web services?

To handle custom exception in JAX-RS based web services, you should create an exception class and then implement the ExceptionMapper interface. super("No File found with given name !!"); 2. How to throw exception from REST API Now you can throw MissingFileException when ever user requested file is not found in desired location.

How to throw a missingfileexception in Jersey exceptionmapper?

Now you can throw MissingFileException when ever user requested file is not found in desired location. throw new MissingFileException (fileName + " does not existing on this server !!"); throw new IOException ("Error while reading file :: '"+fileName+"' !!"); 3. Jersey exception handling example Now is the time to test jersey exceptionmapper.

What happens if an exception is not declared specifically in XML?

Here, if any exception occurred and it is not declared to be handled specifically in the web.xml, then the server will show the Exception.jsp page, because all exceptions are subtypes of the Throwable type. Note that the most specific exception type is chosen if there are multiple matches.


1 Answers

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:

  • JAX-RS — How to return JSON and HTTP Status code together?
  • how can i return response status 405 with empty entity?
  • Bean Validation 400 errors are returning default error page (html) instead of Response entity (json)
like image 184
unwichtich Avatar answered Oct 10 '22 07:10

unwichtich