users@servlet-spec.java.net

[servlet-spec users] Re: Clarification of ServletRequestListener

From: Mark Thomas <markt_at_apache.org>
Date: Mon, 12 Jan 2015 09:32:53 +0000

On 01/01/2015 11:07, Greg Wilkins wrote:
>
> On 31 December 2014 at 20:03, Mark Thomas <markt_at_apache.org
> <mailto:markt_at_apache.org>> wrote:
>
> > - I don't think any of the possible contexts (original / async started / dispatch
> > destination ) are correct, so I would prefer to say that no context is
> > associated with a request that is not synchronously dispatched.
>
> I'm yet to be convinced that calling startAsync should remove a
> request/response pair from a context. I'm open to being convinced but at
> the moment I'm still of the view:
>
>
>
> I'm not saying that startAsync should remove a request/response pair
> from a context.
> I'm saying that returning from a dispatch to a context should remove
> that request/response pair from the context - regardless of if
> startAsync has been called or not.

Ah. Light dawns (finally).

> The only real issue I see is what is the associated context when the
> dispatched thread has returned from the initial dispatched context and
> startAsync has been called. So for example:
>
> * dispatch to context A (enter A listener called & associated context
> is A)
> * dispatch to context B (enter B listener called & associated context
> is B)
> * startAsync called (associated context is still B)
> * return from context B (leave B listener called & associated context
> is A)
> * return from context A (leave A listeners called? & associated
> context is ? )
>
> I see three options:
>
> 1. B the context that called startAsync - yuck! It's like going to the
> bathroom at a party and coming out in a different party. There is
> also the confusion of when the enter/exit listeners should be called
> - does the request leave B then reenter?
>
> 2. A the original context that was dispatched to. This effectively
> means that if the request is async, the context is never null but is
> left as the last context the request was in. I'm kind of OK with
> this, except that it makes the enter/exit listeners complex to
> implement/describe. Any resources allocated by enter/exit
> resources will be held during the async period - so we will need
> another set of listeners to represent the async events.
>
> 3. no context. This is the clearest and simplest. It allows us to say
> that when a dispatched thread leaves a context, the association ends
> and the listeners are called and this is not dependent on any
> asynchronous state.
>
> I think currently jetty implements 3) for the listeners and 2) for the
> getContextPath methods. I think my preference is for 3) which in full is:
>
> * dispatch to context A (enter A listener called & associated context
> is A)
> * dispatch to context B (enter B listener called & associated context
> is B)
> * startAsync called (associated context is still B)
> * return from context B (leave B listener called & associated context
> is A)
> * return from context A (leave A listener called & associated context
> is null )
>
> Simplest and forces async threads to not rely on associated contexts at all.

Of the options you present, I also prefer 3.

However, the part I dislike about this is that a call to
getServletContext() from an async started thread is going to return
different values depending on timing. That strikes me as a recipe for
application bugs. This brings us back to which methods are valid
when/where for async. I think I am saying anything context related is
invalid for anything other than a container thread.

> cheers
>
> PS. We still have the issue of poorly named enter/exit listeners.
> Perhaps we need new ones with better names and deprecate the
> create/destroy ones?

I think that is the best option. Something like:

public interface ServletDispatchListener extends EventListener {
  void requestStart (ServletDispatchEvent sre);
  void contextEntry (ServletDispatchEvent sre);
  void contextExit (ServletDispatchEvent sre);
  void requestEnd (ServletDispatchEvent sre);
}

Mark