On Aug 6, 2009, at 11:41 PM, Bao,Sam wrote:
> In the writeTo method in AbstractRootElementProvider, it doesn’t
> catch for MarshalException similar to how the readFrom method
> catches the UnmarshalException in line 99. So the resource is still
> return a 200 status with no response entity.
>
What HTTP container are you using. Servlet?
What version of the code are you looking at? here is the trunk:
public final void writeTo(
Object t,
Class<?> type,
Type genericType,
Annotation annotations[],
MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException {
try {
final Marshaller m = getMarshaller(type, mediaType);
final Charset c = getCharset(mediaType);
if (c != UTF8) {
m.setProperty(Marshaller.JAXB_ENCODING, c.name());
}
writeTo(t, mediaType, c, m, entityStream);
} catch (JAXBException cause) {
throw ThrowHelper.withInitCause(cause,
new
IOException(ImplMessages.ERROR_MARSHALLING_JAXB(t.getClass()))
);
}
}
It catches JAXBException and MarshalException extends from that and re-
throws it as an IOException.
If the above code is the same as what you are looking at then an
IOException should be thrown which is passed to the underlying HTTP
container (e.g. servlet layer) and a 500 response should be returned
if one of the following is not occurring:
1) If you are using the LW HTTP server, there was a bug in that server
(which has been worked around in the trunk)
which does not react to exceptions passed to it; or
2) If some bytes of the JAXB object have been written to the output
stream and sent out on the TCP connection then a client
may receive the 200 status code and headers, but the client
should observe a terminated connection from the server.
I think what i should to is change the code to throw a
WebApplicationException(500) instead of wrapping in an IOException.
That should give you the chance to map WebApplicationException if the
response has not been committed (no bytes written out). But as i noted
if some bytes of the response have already been written there is not
much that can be done. To reliably catch marshaling errors it would be
necessary to buffer the response before it is written on the wire.
So in summary i think there are two things that can be done to improve
the situation:
1) the writers throw WebApplicationException(500, ex); and
2) define a response filter to buffer the response so that errors can
be trapped when writing.
Paul.
> So I had previously asked about how to handle the
> WebApplicationException with status 400, and so I was thinking that
> likewise it would apply to MarshalException except for the fact that
> it’s never caught and rethrow WebApplicationException for my
> exception mapper to handle. What is the reason MarshalException is
> not caught? Is it intentional or an oversight? I’m leaning towards
> the former and thus would like to understand the reason. Mainly
> because I’m still getting a 200 status which is definitely not
> correct. In the meantime, how should I handle being able to return
> my own status code and response entity? I thought about validating
> and marshalling the xml myself. The other was to extend
> AbstractRootElementProvider and override the writeTo method. I’m
> leaning towards the first idea, but I’d like to hear other
> suggestions and comments.
>
> Thanks.
>
> CONFIDENTIALITY NOTICE This message and any included attachments are
> from Cerner Corporation and are intended only for the addressee. The
> information contained in this message is confidential and may
> constitute inside or non-public information under international,
> federal, or state securities laws. Unauthorized forwarding,
> printing, copying, distribution, or use of such information is
> strictly prohibited and may be unlawful. If you are not the
> addressee, please promptly delete this message and notify the sender
> of the delivery error by e-mail or you may call Cerner's corporate
> offices in Kansas City, Missouri, U.S.A at (+1) (816)221-1024.