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

[jsr339-experts] Re: JAX-RS 2.0 API for asynchronous server-side request processing

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Tue, 02 Aug 2011 14:18:29 +0200

On 07/29/2011 06:21 PM, Markus KARG wrote:
>>>>> The target of decoupling can be reach rather easily:
>>>>> @GET Future<MyEntity> getAsync() { /* Use Executor to return Future
>>>> instance */ }
>>>>> In case the return type is "Future<?>" the JAX-RS runtime can
>> safely
>>>>> assume that the method will return without providing a physical
>> result.
>>>>> The thread can return, and as soon as the Future is provided it can
>>>>> pick up work again and send back the response. No need for any
>>>>> additional complexity or annotations.
>>>> Does it mean that some JAX-RS thread has to be blocked while waiting
>>>> for the response? Also, if we decide to go with
>>>> your simplified proposal, how would you later evolve it into
>> something
>>>> suitable for a Pub/Sub support?
>>>
>>> The calling thread is not getting blocked, as the method obviously
>> returns immediately having a Future in hands. The JAX-RS engine sees
>> the fact that it is a Future and knows "Hey, the result will be
>> provided later, so let's put that one on a stack for now and continue
>> with some different work.". In fact, the identification of Future
>> allows the same thread to do other work instead of getting blocked. It
>> can be used to answer a different response for example, or for any
>> other asynchronous work that is queued by the engine (like asynchronous
>> logging in the background for example, or re-balancing work queues).
>> The creation of the future is done by an ExecutorService, hopefully one
>> provided by the container, so the container admin has control over
>> number of threads and priorities etc. Certainly we could allow private
>> Executors (Java SE, created manually) also, but certainly a shared
>> ExecutorService is more efficient.
>>
>> My point is that there has to be a (set of) thread(s) that periodically
>> checks if the futures are complete. These
>> threads are effectively blocked actively waiting and consuming
>> resources.
>
> As I already described, if the JAX-RS spec enforces that a JAX-RS engine must provide an ExecutorService, that service could create Feature implementations that can execute a callback inside of the engine implicitly which makes the response get send. That way, neither polling nor blocking is needed. It is completely lightweight and callback driven, but it is implicitly working, while your proposal enforces explicit efforts on behalf of the user. That's why I think my proposal is more user friendly.

Well, to me any hidden contract between a Future return type and a implicitly provided ExecutorService is just adding
potential confusion - one needs to really know the details of the spec-enforced rules for the implementation providers
to be able to fully understand the API. That sounds to me like leaking the impl details into an API.

>
>> Also, it would be IMHO difficult to prove that a shared and JAX-RS
>> provider managed ES is going to be more efficient to
>> a custom ES in the open set of use cases we face.
>
> You actually fear that a JAX-RS engine provides an ExecutorService which is worse than one provided by an average application programmer...? Really?

No. I fear that:
- there may be a use-case where a single ES just does not fit the problem being solved.
- Adding ES management & provisioning would make the JAX-RS API less cohesive.

>
>>> Pub/Sub support is currently not on our agenda
>> I disagree.
>
> Maybe I am temporarily blind, but where in our mission charter is pub/sub mentioned?

Forget pub/sub. Wrong term. My bad. Full stop. As for resuming multiple requests based on a single async event, I really
don't see any issue wrt. our charter. We state we will provide async support. We don't specify the details of the
support in the charter. Just because a feature is not explicitly listed in the charter doesn't mean the feature is not
currently on our agenda.

>>> and I actually doubt it is RESTful.
>>
>> Unless you provide some additional reasoning, the argument is kind of
>> cheap :)
>
> Yes it is cheap, but we do JAX-RS not JAX-OtherCoolStuff, do we? ;-)

You don't seem to understand. My point is that it's easy to claim that something is not RESTful. Proving it is the
harder part.

>
> In fact, I often had wished that there would be some kind of merger of Servlet API and JAX-RS as in fact a lot of applications are not quite RESTful but just simpler to do with JAX-RS than with Servlet API. So I do understand that pub/sub is an interesting thing to cover (and in fact I would love to have http based pub/sub support in our application to get rid of proprietary JMS streams), but I actually do not think that this is really part of our current mission statement. Pub/Sub in future will be done by lots of applications using WebSockets for example, and those are explicitly excluded. So what sense would it make to provide pub/sub, if we do not provide WebSockets support?

No-one is ruling out proprietary support for comet or websockets. We would however not put it into the API, since this
area needs more experimenting.

>>> Anyways, if we decide to do Pub/Sub then a programmer could use
>> something rather simple as a @Singleton EJB queue for messages, into
>> which any @POST method can post (na additional magic needed). The
>> distribution is just as simple: Someone asking for the next message (in
>> the COMET sense) invoked @GET which returned Future<Message>. The
>> response is kept on hold, the thread is free to do something different
>> meanwhile. When the singleton receives a post, it looks up all the
>> waiting Futures and fulfils them. Waiting does not necessarily mean
>> "active spinning" or "being idle", but it can be done in a way that
>> works with posting work in executors as soon as messages are there to
>> get distributed. The singleton just needs a reference to the response-
>> sending engine to put the filled Futures on a send queue (what you
>> called "AsyncContext" if I remember correctly).
>>
>> Not all JAX-RS users run their apps in a full JavaEE environment. I
>> would prefer we don't try to introduce features that
>> conditionally work only in some environments.
>
> It was just one possible solution to the mentioned problem. There can be other solutions which will work in Java SE. BTW, in times of embedded GlassFish and Web Profiles, why should one actually use JAX-RS in a non EE environment?

I don't know. Maybe because one is an OSGi or Spring purist or wants to run the service in Google AppEngine or ...

>
>>>
>>> Do I oversee something?
>>
>> The EJB dependency of such solution.
>
> See above.
>
>>
>>>
>>>>> If we want to give the server more control on the threads, we could
>>>> add something like "getExecutorService()" to the context to prevent
>>>> people from creating their own executors.
>>>>
>>>> IMHO, this may certainly be useful but I can also imagine people
>> want
>>>> to use their own ES in many async cases. Would
>>>> that be possible?
>>>
>>> Yes certainly. My proposal says that the JAX-RS engine identifies the
>> fact whether to immediately be async or not just by "if instanceof
>> Future". Where the ExecutorService comes from is of no interest for
>> this. We can inject on provided by the container, but a user can also
>> just use the Java SE Executors factory or what ever he likes to provide
>> a Future. Future just serves as an async indicator to prevent another
>> annotation.
>>
>> Let me think more about using the future as the async indicator and how
>> it would work in a bigger picture.
>
> Ok.
>
>>>
>>>>> So, the question is: Do we need anything more complex like this? I
>>>> actually would say "no" in the first draft, as e.g. COMET is not a
>>>> target of JAX-RS 2.0 according to the project description on JCP.org
>> (I
>>>> would accept that complexity if COMET would be a target).
>>>>
>>>> Not all pub/sub scenarios need to use Comet. Scenario in which one
>> or
>>>> more requests are waiting for another request from
>>>> another client to resume seems quite common.
>>>
>>> Seems you more care for Pub/Sub than for async. ;-)
>>
>> Actually, I do care for both. A feature of resuming multiple responses
>> based on a single event seems interesting enough
>> to explore it in more detail.
>
> Yes certainly it is. But it shouldn't be used as the silver bullet that kills simplicity for all others that do not need pub/sub but just want to get rid of long running process delay or lots of blocked container threads.

What makes you think that we would kill the simplicity because of supporting this additional feature?

>
>>> What scenario do you have in mind that is not possible with my
>> proposal?
>>
>> It's not a question of being possible or not. If we just provide a way
>> of resuming a single request, then everything is
>> possible. It does not however mean that it would be easy at the same
>> time. I am shooting for making it easy.
>
> Actually I thought my proposal IS more easy than yours...?!

Seems to me that you had to provide lot of additional details to explain how it's supposed to work in this forum. There
are hidden details that make it less understandable IMO.

Marek