jsr339-experts@jax-rs-spec.java.net

[jsr339-experts] Re: AsyncResponse unmapped exception and CompletionCallback

From: Bill Burke <bburke_at_redhat.com>
Date: Fri, 08 Feb 2013 16:39:48 -0500

On 2/8/2013 4:18 PM, Sergey Beryozkin wrote:
> On 08/02/13 14:18, Sergey Beryozkin wrote:
>> Hi,
>> I've been experimenting with throwing unmapped exceptions via
>> AsyncResponse.resume(Throwable); and expecting to see a registered
>> CompletionCallback.onComplete(Throwable) be invoked in such cases, with
>> the runtime making sure the underlying javax.servler.AsyncListener
>> onComplete and onError callbacks delegating to
>> CompletionCallback.onComplete(Throwable).
>>
>> What I'm seeing is that CompletionCallback.onComplete(Throwable) is
>> indeed called in case of unmapped exceptions, but via
>> AsyncListener.onComplete path, and thus,
>> CompletionCallback.onComplete(Throwable) having a null Throwable.
>>
>> What I'm not sure if it is the JAX-RS implementation problem or that of
>> the underlying javax.servlet.AsyncContext's implementation ?
>>
>> In other words, how to get it call back AsyncListener.onError() ?
>
> OK, I'm thinking I've got it. It is the responsibility of the JAX-RS
> runtime to ensure that the unmapped exception can be made visible to
> CompletionCallback,
> Marek - if it is not the case please correct me, but I think this is how
> it should work,
>
> Now, back to that updated AsyncResponse.resume() Javadocs update:
> "except that unmapped exceptions are not re-thrown by JAX-RS runtime to
> be handled by a hosting I/O container. Instead, any unmapped exceptions
> are propagated to the hosting I/O container via a container-specific
> callback mechanism. Depending on the container implementation,
> propagated unmapped exceptions typically result in an error status
> being sent to the client and/or the connection being closed."
>
> FYI, rethrowing it works with Jetty - but not with Tomcat.
>
> Either way, why can't we simply say that "unmapped exceptions will
> result in 500 status being sent to the client" and thus make it up to
> the given JAX-RS implementation to ensure it is the case ?
>

I don't think you need to worry about Servlet 3.0 callbacks. This is
the way we implement resume(Object)

try {
   - Create a 200 Response with the resume() parameter if it is not a
Response already
   - Set the content-type based on Accept parameters and original JAX-RS
method
   - filter the response
   - Call WriterInterceptor/MBW chain
} catch (Throwable ex) {
    return resume(ex);
}

- Servlet 3.0 asyncContext.complete();
- invoke callbacks (null)

The resume(Throwable) looks like this:

try {
    if (mappable(throwable)) map;
    else sendError(500);
} catch (Throwable ignore) {
   log exception
}
finally {
    servlet3 asyncContext.complete();
}

invoke completion callbacks(throwable);


-- 
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com