users@jersey.java.net

Re: [Jersey] Async support proposal in the Jersey client API

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 06 Aug 2009 15:02:12 +0200

Hi,

Here is what i have currently implemented:

   https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea-SNAPSHOT/jersey/com/sun/jersey/api/client/AsyncWebResource.html
   https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea-SNAPSHOT/jersey/com/sun/jersey/api/client/AsyncListener.html

The next steps are to abstract out the threading logic so one can
defer to an async implementation. This may be tricky and i am not sure
if i can retain backwards compatibility with the client filters.

The problem i am currently wrestling with is that the filters are
stack based, which means for any integration with a lower-level async
API we need to make the Jersey calling thread wait until an event is
received and then resume it (so the stack of the filters can unwind).

This means any a call to the Jersey layer needs to kick off a new
thread and return Future. Then the async layer of the HTTP client is
likely to reuse another thread from its thread pool to make the
underlying request, then the request is suspended, and thread can be
reused for other requests, when a response arrives arrives an event is
produced and the Jersey thread is woken up with the appropriate data,
the filter stack unwinds and a Jersey event is produced.

The above seems rather complicated and i am not sure if it defeats the
purpose of any async HTTP client library using a thread pool. If the
client filters were not stack based it would be possible to defer just
to the threading logic of the async HTTP library.

Paul.


On Aug 4, 2009, at 9:42 AM, Paul Sandoz wrote:

>
> On Aug 3, 2009, at 5:49 PM, Marc Hadley wrote:
>
>> On Aug 3, 2009, at 11:16 AM, Paul Sandoz wrote:
>>>>>
>>>>>> Take a look at Dispatch<T>, AsyncHandler<T> and Response<T> in
>>>>>> JAX-WS, they do the same kind of thing.
>>>>>>
>>>>>
>>>>> Thanks.
>>>>>
>>>>> The use of Future<?> is really handy, thus CallBackStatus is not
>>>>> really required.
>>>>>
>>>>> In the AsyncHandler.handleResponse why is the parameter
>>>>> Response<T> that extends from Future<T>. Is that just for
>>>>> convenience as a holder of T and to get the response context ?
>>>>> or can this handler get called if the request is cancelled ?
>>>>>
>>>>
>>>> The parameter is a Response<T> so that any exceptions can be
>>>> thrown from the get method just as they would using a sync API.
>>>> If you just pass T to the handler then you lose the ability to
>>>> throw exceptions.
>>>>
>>>
>>> OK. In this context not all methods on Future make sense, e.g. get
>>> with a timeout or cancel ? and i suppose isDone should return true?
>>>
>> Right. The AsyncHadler method isn't called until the op completes
>> so get with a timeout is just the same as a get without and returns
>> right away. Cancel won't work as its too late but one thing you
>> need to decide is whether cancel on the Future<?> returned from the
>> invokeAsync method equivalent should result in a call to the
>> handler with isCancelled returning true, or no call to the handler
>> - I can't recall without looking which way we jumped in JAX-WS.
>>
>
> Future does throw a CancellationException on get.
>
>
>>> I was proposing a separate method to handle exceptions. But from
>>> the perspective of the synchronous API i wonder if it make sense
>>> to keep the same pattern of catching exceptions.
>>>
>> I think catching exceptions is more natural and lets the developer
>> easily do different things for different exceptions without a lot
>> of instanceof checking. It also aligns the callback and polling
>> variants better IMO.
>>
>
> After some more thought, i am not sure this really applies to async
> events, the reason is it is very easy for a runtime exception to be
> swallowed because the developer forgot to wrap the get around a try/
> catch. I would expect such exceptions would not stop the application
> if not caught or produce a 500 response if called from within a
> service.
>
> Thus it might be better to explicitly require a different event on
> an error so the developer is explicitly aware.
>
> Paul.
>
>> Marc.
>>
>>>>>>
>>>>>> On Aug 3, 2009, at 5:53 AM, Paul Sandoz wrote:
>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> Async support on the server-side is important for scalability.
>>>>>>>
>>>>>>> Equally important is a client side solution, which if services
>>>>>>> are clients, is also important for scalability, or for good
>>>>>>> interaction with UIs that need to process stuff asynchronously
>>>>>>> to avoid pauses.
>>>>>>>
>>>>>>> There is the AsyncWebResource class that supports Future<T>,
>>>>>>> but we need to extend this to support callbacks.
>>>>>>>
>>>>>>> So we could do the following:
>>>>>>>
>>>>>>> AsyncWebResource r = ...
>>>>>>>
>>>>>>> CallBackStatus s = r.get(new CallBack<String>() {
>>>>>>> void onError(Throwable e) { ... }
>>>>>>>
>>>>>>> void onResponse(String s) { ... }
>>>>>>> });
>>>>>>>
>>>>>>>
>>>>>>> The CallBackStatus instance can be used to check the status
>>>>>>> and also cancel.
>>>>>>>
>>>>>>> (CallBack and CallBackStatus are not very good names).
>>>>>>>
>>>>>>>
>>>>>>> Because of type erasure, the "String" type in the above
>>>>>>> example needs to be known. It seems appropriate to make
>>>>>>> CallBack an abstract class from which the type T can be
>>>>>>> determined:
>>>>>>>
>>>>>>> public abstract class CallBack<T> {
>>>>>>> protected CallBack() {
>>>>>>> // Determine concrete Type of T
>>>>>>> }
>>>>>>>
>>>>>>> protected CallBack(Class<T> c) {
>>>>>>> this.type = c;
>>>>>>> }
>>>>>>>
>>>>>>> Type getType() { ... }
>>>>>>>
>>>>>>> public abstract void onError(Throwable e);
>>>>>>>
>>>>>>> public abstract void onResponse(T t);
>>>>>>>
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> Then we require the ability to utilize async client APIs if
>>>>>>> they are available from the underlying client implementation
>>>>>>> or a default implementation that utilizes its own threading
>>>>>>> logic if there is no async support in the underlying
>>>>>>> implementation.
>>>>>>>
>>>>>>> Paul.
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>>
>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>