users@jersey.java.net

Re: [Jersey] Returning XML validation failure info in responses

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 14 Apr 2010 10:05:13 +0200

On Apr 13, 2010, at 9:35 PM, Marc Hadley wrote:

> On Apr 13, 2010, at 1:12 PM, Brian Buderman wrote:
>>
>> I see how to register a ContextResolver<Unmarshaller> such that an
>> unmarshaller is created with a schema to validate against. The
>> validation then occurs during POST/PUT, and does fail, throwing an
>> UnmarshalException with a linked SAXParseException. It seems the
>> Jersey server code then catches that, and turns it into a
>> WebApplicationException with response code 400.
>>
>> What would be the recommended way to propagate the details from
>> SAXParseException into the response? Registering an ExceptionMapper
>> doesn't seem proper as the error is wrapped in a
>> WebApplicationException.
>>
>> I've tried using Jersey 1.0.3 and 1.1.5.1, with JAXB 2.1.12.
>>
> What happens if you include an ExceptionMapper for
> UnmarshalException ?
>

That will not work because the JAXB reader wraps the
UnmarshalException around a WebApplicationException.

     public final Object readFrom(
             Class<Object> type,
             Type genericType,
             Annotation annotations[],
             MediaType mediaType,
             MultivaluedMap<String, String> httpHeaders,
             InputStream entityStream) throws IOException {

         try {
             return readFrom(type, mediaType, getUnmarshaller(type,
mediaType), entityStream);
         } catch (UnmarshalException ex) {
             throw new WebApplicationException(ex, 400);
         } catch (JAXBException ex) {
             throw new WebApplicationException(ex, 500);
         }
     }

Two suggestions:

1) map WebApplicationException and check the cause, if the cause is
not what you expect return the response from
      the WebApplicationException, otherwise look at the exception and
generate a response.

2) map WebApplicationException and inject @Context Providers ps. Map
UnmarshalException.
      Then in the mapped WebApplicationException check if there is an
exception mapper for the cause by calling
      ps.getExceptionMapper(cause). If non-null return the response
from that mapper, otherwise return the response for
      the WebApplicationException.


I think we could support something in Jersey along the approach of 2).
Namely Jersey defined a DeferredWebApplicationException and
DeferredWebApplicationExceptionMapper (which is registered by Jersey).
The JAXB stuff throws DeferredWebApplicationExceptionMapper which
means you could register an exception mapper for UnmarshalException or
JAXBException. The DeferredWebApplicationExceptionMapper could ensure
the status code of the response in WebApplicationException correctly
takes priority.

Could you log an issue?

Thanks,
Paul.


Paul.