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?
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:
上一篇: 我如何从资源发送响应代码和内容?