users@jersey.java.net

Re: [Jersey] How to customize ExceptionMapper's response format

From: William Zhou <wlmzhou_at_yahoo.com>
Date: Thu, 18 Jun 2009 01:06:16 -0700 (PDT)

Paul,

Thanks for the suggestions. I found it work well as you guided if the exception was thrown within my defined methods. The exception entity was in JSON format if I set request header as (Accept: application/json).

But for the NotFoundException, it was thrown by Jersey stack when the resource was not found(i.e. a bad url). I found the exception entity still in XML format. How can I do with such exceptions?

And could you tell me how to do with Option 1? In my applications, I am going to support various media types both in ways of URL and request Header. For example, the consumer can get JSON format response both by setting request header (Accept: application/json) or consume a link like: "http://sampleresource.json".
For the URL consumption, I would like to pass the URI info into the BadRequestExceptionMapper or NotFoundException mapper and specify the media type to the response.

Thanks,
William


Hi William,


On Jun 16, 2009, at 5:28 AM, William Zhou wrote:
Hi,
I am writing a custom exception mapper, saying
BadRequestExceptionMapper<BadRequestException> implements
ExceptionMapper<BadRequestException>.
I am planning to provide more information to the client than just
returning the error status 400 in the mapper, by filling an entity
in the response.
The problem now is that the customer may require to accept xml or
json type in his request. In the error response of
BadRequestExceptionMapper, I would like to convert the entity to the
correct format. However, I did not find a way because the
ExceptionMapper interface only passes the exception into the mapper:
javax.ws.rs.core.Response toResponse(E e) and the format info is lost.
I am wondering is there ways to customize the media type of my error
response?

1) Is it possible to inject the uriInfo or request, which contains
the acceptable media type infomation, into the exception mapper?
Yes.
2) Is it possible to rewriting the response of the
BadRequestExceptionMapper in another provider, which is aiming to do
reformating?
Yes, if you set up the type and media type appropriately. All
exception mapping does is map an exception to a Response instance.
That instance is processed in the same manner as if the instance was
returned from a resource method.
3) Put the media type info in BadRequestException is one way, but
not my prefered.
There is some ambiguity in the HTTP specification about responses >=
300 w.r.t to honoring the acceptable information sent by the client.
Before Jersey invokes a resource method (even before it extracts
information from the HTTP request to method parameters) the most
acceptable media type that matches the resource method will be set as
the Content-Type on the response headers, but only if that media type
is a concrete media type (not a wild card).


So if you have:
@Produces("application/xml", "application/json") public MyJAXBBean get() { ... }
and the method will be invoked the Content-Type will be set to either
XML or JSON. So if you throw an exception from within that method, and
an exception mapper maps that exception to a response with a JAXB
object as the entity, then it should get serialized as XML or JSON.
Does that help?
Paul.