diff --git a/api/src/main/java/jakarta/servlet/AsyncContext.java b/api/src/main/java/jakarta/servlet/AsyncContext.java index 2f9620040..8df88bac4 100644 --- a/api/src/main/java/jakarta/servlet/AsyncContext.java +++ b/api/src/main/java/jakarta/servlet/AsyncContext.java @@ -17,6 +17,8 @@ package jakarta.servlet; +import java.util.concurrent.Executor; + /** * Class representing the execution context for an asynchronous operation that was initiated on a ServletRequest. * @@ -30,15 +32,15 @@ *
@@ -188,6 +190,14 @@ 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. * + *
+ * This method should be called from a container managed invocation associated with the same request, such as + * {@link Servlet#service(ServletRequest, ServletResponse)}, + * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}, {@link ReadListener#onDataAvailable()}, + * {@link WriteListener#onWritePossible()}, {@link AsyncContext#execute(Runnable)}, {@link AsyncContext#run(Runnable)}, + * etc. 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 * @@ -218,6 +228,14 @@ public interface AsyncContext { *
* See {@link #dispatch()} for additional details, including error handling. * + *
+ * This method should be called from a container managed invocation associated with the same request, such as + * {@link Servlet#service(ServletRequest, ServletResponse)}, + * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}, {@link ReadListener#onDataAvailable()}, + * {@link WriteListener#onWritePossible()}, {@link AsyncContext#execute(Runnable)}, {@link AsyncContext#run(Runnable)}, + * etc. 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 * @@ -252,6 +270,14 @@ public interface AsyncContext { *
* See {@link #dispatch()} for additional details, including error handling. * + *
+ * This method should be called from a container managed invocation associated with the same request, such as + * {@link Servlet#service(ServletRequest, ServletResponse)}, + * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}, {@link ReadListener#onDataAvailable()}, + * {@link WriteListener#onWritePossible()}, {@link AsyncContext#execute(Runnable)}, {@link AsyncContext#run(Runnable)}, + * etc. 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 * @@ -277,6 +303,14 @@ public interface AsyncContext { * startAsync 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. + * + *
+ * This method should be called from a container managed invocation associated with the same request, such as + * {@link Servlet#service(ServletRequest, ServletResponse)}, + * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}, {@link ReadListener#onDataAvailable()}, + * {@link WriteListener#onWritePossible()}, {@link AsyncContext#execute(Runnable)}, {@link AsyncContext#run(Runnable)}, + * etc. 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(); @@ -284,10 +318,39 @@ public interface AsyncContext { * Causes the container to dispatch a thread, possibly from a managed thread pool, to run the specified * Runnable. The container may propagate appropriate contextual information to the Runnable. * + * @see #dispatch() * @param run the asynchronous handler */ public void start(Runnable run); + /** + * Causes the container to dispatch a thread, possibly from a managed thread pool, to run the specified + * Runnable. The execution will be mutually excluded from all other container managed invocations for the same + * request, such as {@link Servlet#service(ServletRequest, ServletResponse)}, + * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}, {@link ReadListener#onDataAvailable()}, + * {@link WriteListener#onWritePossible()}, {@link AsyncContext#execute(Runnable)}, {@link AsyncContext#run(Runnable)}, + * etc. The container may propagate appropriate contextual information to the Runnable. + * + * @see #start(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 invocations for + * the same request, such as {@link Servlet#service(ServletRequest, ServletResponse)}, + * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}, {@link ReadListener#onDataAvailable()}, + * {@link WriteListener#onWritePossible()}, {@link AsyncContext#execute(Runnable)}, {@link AsyncContext#run(Runnable)}, + * etc. The container may propagate appropriate contextual information to the Runnable. + * + * @see #start(Runnable) + * @param run the asynchronous handler + */ + public void run(Runnable run); + /** * 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. diff --git a/api/src/main/java/jakarta/servlet/ServletRequest.java b/api/src/main/java/jakarta/servlet/ServletRequest.java index 765955cac..c15612488 100644 --- a/api/src/main/java/jakarta/servlet/ServletRequest.java +++ b/api/src/main/java/jakarta/servlet/ServletRequest.java @@ -441,7 +441,7 @@ public interface ServletRequest { * * @throws IllegalStateException if this request is within the scope of a filter or servlet that does not support * asynchronous operations (that is, {@link #isAsyncSupported} returns false), or if this method is called again without - * any asynchronous dispatch (resulting from one of the {@link AsyncContext#dispatch} methods), is called outside the + * any asynchronous dispatch (resulting from one of the {@link AsyncContext#execute} methods), is called outside the * scope of any such dispatch, or is called again within the scope of the same dispatch, or if the response has already * been closed * @@ -494,7 +494,7 @@ public interface ServletRequest { * * @throws IllegalStateException if this request is within the scope of a filter or servlet that does not support * asynchronous operations (that is, {@link #isAsyncSupported} returns false), or if this method is called again without - * any asynchronous dispatch (resulting from one of the {@link AsyncContext#dispatch} methods), is called outside the + * any asynchronous dispatch (resulting from one of the {@link AsyncContext#execute} methods), is called outside the * scope of any such dispatch, or is called again within the scope of the same dispatch, or if the response has already * been closed * @@ -512,7 +512,7 @@ public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse se * *
* This method returns false if this request was put into asynchronous mode, but has since been dispatched
- * using one of the {@link AsyncContext#dispatch} methods or released from asynchronous mode via a call to
+ * using one of the {@link AsyncContext#execute} methods or released from asynchronous mode via a call to
* {@link AsyncContext#complete}.
*
* @return true if this request has been put into asynchronous mode, false otherwise
@@ -564,7 +564,7 @@ public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse se
* request dispatched via {@link RequestDispatcher#forward(ServletRequest, ServletResponse)} or
* {@link RequestDispatcher#include(ServletRequest, ServletResponse)} is given as DispatcherType.FORWARD
or
* DispatcherType.INCLUDE
, respectively, while the dispatcher type of an asynchronous request dispatched
- * via one of the {@link AsyncContext#dispatch} methods is given as DispatcherType.ASYNC
. Finally, the
+ * via one of the {@link AsyncContext#execute} methods is given as DispatcherType.ASYNC
. Finally, the
* dispatcher type of a request dispatched to an error page by the container's error handling mechanism is given as
* DispatcherType.ERROR
.
*
diff --git a/api/src/main/java/jakarta/servlet/ServletRequestWrapper.java b/api/src/main/java/jakarta/servlet/ServletRequestWrapper.java
index 73b94ab3f..93e36bd35 100644
--- a/api/src/main/java/jakarta/servlet/ServletRequestWrapper.java
+++ b/api/src/main/java/jakarta/servlet/ServletRequestWrapper.java
@@ -348,7 +348,7 @@ public ServletContext getServletContext() {
*
* @throws IllegalStateException if the request is within the scope of a filter or servlet that does not support
* asynchronous operations (that is, {@link #isAsyncSupported} returns false), or if this method is called again without
- * any asynchronous dispatch (resulting from one of the {@link AsyncContext#dispatch} methods), is called outside the
+ * any asynchronous dispatch (resulting from one of the {@link AsyncContext#execute} methods), is called outside the
* scope of any such dispatch, or is called again within the scope of the same dispatch, or if the response has already
* been closed
*
@@ -372,7 +372,7 @@ public AsyncContext startAsync() throws IllegalStateException {
*
* @throws IllegalStateException if the request is within the scope of a filter or servlet that does not support
* asynchronous operations (that is, {@link #isAsyncSupported} returns false), or if this method is called again without
- * any asynchronous dispatch (resulting from one of the {@link AsyncContext#dispatch} methods), is called outside the
+ * any asynchronous dispatch (resulting from one of the {@link AsyncContext#execute} methods), is called outside the
* scope of any such dispatch, or is called again within the scope of the same dispatch, or if the response has already
* been closed
*