users@jersey.java.net

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

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 18 Jun 2009 13:33:25 +0200

On Jun 18, 2009, at 10:06 AM, William Zhou wrote:

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

For such exceptions when the "Content-Type" is not set you can utilize
HttpHeaders.getAcceptableMediaTypes() and set the "Content-Type" from
that.

If you like you can also inject HttpContext, then do get the
HttpRequestContext from that and call getAcceptableMediaType passing
in a list of concrete media types (namely the same list you would
declare on the @Produces of a resource method):

https://jersey.dev.java.net/nonav/apidocs/1.1.0-ea/jersey/com/sun/jersey/api/core/HttpRequestContext.html
#getAcceptableMediaType(java.util.List)


e.g.

   @Context HttpContext hc = ...

   ...

   if (content type not set) {
     List<MediaType> xmlAndJson = ...
     MediaType x = hc.getAcceptableMediaType(xmlAndJson);
     if (x == null)
       x = xmlAndJson.get(0);

     // set the content type
   }


If this works for you we can probably encapsulate the above
functionality in some method on the HttpResponseContext.


>
>
> 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".

See the following thread:

http://markmail.org/search/?q=list%3Anet.java.dev.jersey.users+getMediaTypeMappings#query
:list%3Anet.java.dev.jersey.users%20getMediaTypeMappings%20order
%3Adate-backward+page:1+mid:far7r6bpmfnyukl3+state:results

Paul.

>
> 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.
>
>
>