users@servlet-spec.java.net

[servlet-spec users] [jsr369-experts] SERVLET_SPEC-109: AsyncContext#complete will not take effect

From: Shing Wai Chan <shing.wai.chan_at_oracle.com>
Date: Tue, 21 Mar 2017 16:02:21 -0700

SERVLET_SPEC-109: AsyncContext#complete will not take effect

I am looking at an issue about AsyncContext#complete [1]

Let us consider the following scenario inside a HttpServlet#doGet:
    AsyncContext ac = req.startAsync();
    ...
    ac.complete();
    boolean start = req.isAsyncStarted(); (A)

Is 'start' true or false in (A)?

We have the following from Javadoc:
a) AsyncContext#complete:
    Completes the asynchronous operation that was started on the request that
was used to initialze this AsyncContext, closing the response that was used
to initialize this AsyncContext.

b) ServletRequest#isAsyncStarted:
    Checks if this request has been put into asynchronous mode.
    A ServletRequest is put into asynchronous mode by calling startAsync() or
startAsync(ServletRequest,ServletResponse) on it.
    This method returns false if this request was put into asynchronous mode,
but has since been dispatched using one of the AsyncContext.dispatch()
methods or released from asynchronous mode via a call to
AsyncContext.complete().

However, in Servlet spec, we have the following for AsyncContext#complete.
    If this method is called before the container-initiated dispatch that
called startAsync has returned to the
container, then the call will not take effect until after the
container-initiated dispatch has returned to the container. Invocation of the
AsyncListener.onComplete(AsyncEvent) will also be delayed till after the
container-initiated dispatch has returned to the container.

Note that there is a similar paragraph in AsyncContext#dispatch as follows:
If any of the dispatch methods are called before the container-initiated dispatch
that called startAsync has returned to the container, then the call will not take
effect until after the container-initiated dispatch has returned to the container.
Invocation of the AsyncListener.onComplete(AsyncEvent), AsyncListener.onTimeout(AsyncEvent)and
AsyncListener.onError(AsyncEvent) will also be delayed till after the
container-initiated dispatch has returned to the container.

Since AsyncContext#complete "will not take effect until after the container-initiated
dispatch has returned to the container.", we will have
    start = true // in (A) above

I plan to clarify the spec as follows:
a) AsyncContext#complete:
    If this method is invoked before the container-initiated dispatch that called startAsync
    has returned to the container, the following conditions must hold during that time
    between the invocation of complete and the return of control to the container:

    * the behavior specified for complete will not take effect until after
      the startAsync caller has returned to the container.

    * any AsyncListener.onComplete(AsyncEvent) invocations will
      also be delayed until after the startAsync caller has returned to the
      container.

    * any calls to request.isAsyncStarted() must return true until
      after the startAsync caller has returned to the container.


b) AsyncContext#dispatch
    If any of the dispatch methods are invoked before the container-initiated dispatch
    that called startAsync has returned to the container, the following conditions must
    hold during that time between the invocation of complete and the return of control
    to the container:

    * any dispatch invocations invoked during that time will not take
      effect until after the startAsync caller has returned to container.

    * any AsyncListener.onComplete(AsyncEvent),
      AsyncListener.onTimeout(AsyncEvent) or
      AsyncListener.onError(AsyncEvent) invocations will also be delayed
      until after the startAsync caller has returned to the container.

    * any calls to request.isAsyncStarted() must return true until
      after the startAsync caller has returned to the container.


Please let me know your comments.
Thanks.
     Shing Wai Chan


[1] https://java.net/jira/browse/SERVLET_SPEC-109