Skip to content

Commit

Permalink
Fix jakartaee#412 AsyncContext execute
Browse files Browse the repository at this point in the history
Fix jakartaee#412 AsyncContext is an Executor that mutually excludes from other container invocations for the same request.
  • Loading branch information
gregw committed Jul 29, 2021
1 parent 54c8edb commit cc5a6d4
Showing 1 changed file with 67 additions and 1 deletion.
68 changes: 67 additions & 1 deletion api/src/main/java/jakarta/servlet/AsyncContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

package jakarta.servlet;

import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;

/**
* Class representing the execution context for an asynchronous operation that was initiated on a ServletRequest.
*
Expand All @@ -36,9 +39,17 @@
* {@link #dispatch} methods, call {@link #complete}.</li>
* </ol>
*
* <p>
* An AsyncContext is an {@link Executor} that provides mutual exclusion between container managed threads for the
* same request. Specifically container managed threads are used for calls to
* {@link Servlet#service(ServletRequest, ServletResponse)},
* {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)},
* {@link ReadListener#onDataAvailable()}, {@link WriteListener#onWritePossible()}
* and to call the {@link Runnable}s passed to {@link AsyncContext#execute(Runnable)} and {@link AsyncContext#run(Runnable)}.
*
* @since Servlet 3.0
*/
public interface AsyncContext {
public interface AsyncContext extends Executor {

/**
* The name of the request attribute under which the original request URI is made available to the target of a
Expand Down Expand Up @@ -188,6 +199,11 @@ public interface AsyncContext {
* within the same asynchronous cycle will result in an IllegalStateException. If startAsync is subsequently called on
* the dispatched request, then any of the dispatch or {@link #complete} methods may be called.
*
* <p>
* This method should be called from a container managed thread associated with the same request.
* A container may log a warning the first time this method is called from a non container managed thread and
* future versions of the specification may prohibit such calls.
*
* @throws IllegalStateException if one of the dispatch methods has been called and the startAsync method has not been
* called during the resulting dispatch, or if {@link #complete} was called
*
Expand Down Expand Up @@ -218,6 +234,11 @@ public interface AsyncContext {
* <p>
* See {@link #dispatch()} for additional details, including error handling.
*
* <p>
* This method should be called from a container managed thread associated with the same request.
* A container may log a warning the first time this method is called from a non container managed thread and
* future versions of the specification may prohibit such calls.
*
* @param path the path of the dispatch target, scoped to the ServletContext from which this AsyncContext was
* initialized
*
Expand Down Expand Up @@ -252,6 +273,11 @@ public interface AsyncContext {
* <p>
* See {@link #dispatch()} for additional details, including error handling.
*
* <p>
* This method should be called from a container managed thread associated with the same request.
* A container may log a warning the first time this method is called from a non container managed thread and
* future versions of the specification may prohibit such calls.
*
* @param context the ServletContext of the dispatch target
* @param path the path of the dispatch target, scoped to the given ServletContext
*
Expand All @@ -277,17 +303,57 @@ public interface AsyncContext {
* <tt>startAsync</tt> has returned to the container, then the call will not take effect (and any invocations of
* {@link AsyncListener#onComplete(AsyncEvent)} will be delayed) until after the container-initiated dispatch has
* returned to the container.
*
* <p>
* This method should be called from a container managed thread associated with the same request.
* A container may log a warning the first time this method is called from a non container managed thread and
* future versions of the specification may prohibit such calls.
*/
public void complete();

/**
* Causes the container to dispatch a thread, possibly from a managed thread pool, to run the specified
* <tt>Runnable</tt>. The container may propagate appropriate contextual information to the <tt>Runnable</tt>.
*
* @see #execute(Runnable)
* @see #run(Runnable)
* @param run the asynchronous handler
*/
public void start(Runnable run);

/**
* Causes the container to dispatch a container managed thread, possibly from a managed thread pool,
* to run the passed <tt>Runnable</tt>. The execution will be mutually excluded from all other container
* managed threads for the same request.
* <p>
* If {@link AsyncContext#complete()} is called, or the request lifecycle completes via a dispatch
* prior to the runnable being run, then it will never be run.
* <p>
* The container may propagate appropriate contextual information to the <tt>Runnable</tt>.
*
* @see #start(Runnable)
* @see #run(Runnable)
* @param run the asynchronous handler
*/
@Override
public default void execute(Runnable run) {
start(() -> run(run));
}

/**
* Executes the given command in the calling thread, mutually excluded from all other container
* managed threads for the same request.
* <p>
* The container may propagate appropriate contextual information to the <tt>Runnable</tt>.
*
* @see #start(Runnable)
* @see #execute(Runnable)
* @param run the asynchronous handler
* @throws CancellationException If {@link AsyncContext#complete()} is called, or the request
* lifecycle completes via a dispatch prior to the runnable being run
*/
public void run(Runnable run) throws CancellationException;

/**
* Registers the given {@link AsyncListener} with the most recent asynchronous cycle that was started by a call to one
* of the {@link ServletRequest#startAsync} methods.
Expand Down

0 comments on commit cc5a6d4

Please sign in to comment.