Class AsyncContextImpl

java.lang.Object
org.apache.catalina.core.AsyncContextImpl
All Implemented Interfaces:
AsyncContext, AsyncContextCallback

public class AsyncContextImpl extends Object implements AsyncContext, AsyncContextCallback
Implementation of AsyncContext that manages the lifecycle of an asynchronous request processing operation. Each instance is associated with a single request object. If an asynchronous request starts multiple cycles of asynchronous processing, the AsyncContextImpl is re-used for all cycles. Once complete is called or an async dispatch does not trigger a new asynchronous request the AsyncContextImpl is recycled and discarded. It is not re-used.

There is a concurrency risk that comes from applications retaining references to an AsyncContext in non-container threads and trying to use those references beyond the point the references are valid. This has most frequently been observed at shutdown but shutdown is an instance of the more general case of the async request timing out, Tomcat cleaning it up but the application continuing to process on a non-container thread. Other application bugs can have similar results.

To mitigate against concurrency issues:

  • AsyncContext methods that can be called by an application take local copies of any instance variables used, validate the instance is in a valid state and then execute the method.
  • AsyncContext methods that can only be called by Tomcat internal methods don't check state on the basis that Tomcat manages state and only calls those methods when the state is valid.
  • To avoid concurrency issues with the state of the local variables, a dedicated atomic flag hasBeenRecycled tracks whether recycled has been called.
  • Field Details

    • sm

      protected static final StringManager sm
      String manager for localized log messages.
  • Constructor Details

    • AsyncContextImpl

      public AsyncContextImpl(Request request)
      Constructs an AsyncContextImpl for the given request.
      Parameters:
      request - The request associated with this async context
  • Method Details

    • complete

      public void complete()
      Description copied from interface: jakarta.servlet.AsyncContext
      Completes the async request processing and closes the response stream
      Specified by:
      complete in interface AsyncContext
    • fireOnComplete

      public void fireOnComplete()
      Description copied from interface: AsyncContextCallback
      Fires the onComplete event to the associated async context.
      Specified by:
      fireOnComplete in interface AsyncContextCallback
    • timeout

      public boolean timeout()
      Fires the timeout event for this async context.
      Returns:
      true if the timeout was handled successfully
    • dispatch

      public void dispatch()
      Description copied from interface: jakarta.servlet.AsyncContext
      Dispatches the request to the resource at the original request URI, as specified in the original request. After the dispatch, the async request processing is complete and the response is committed.
      Specified by:
      dispatch in interface AsyncContext
    • dispatch

      public void dispatch(String path)
      Description copied from interface: jakarta.servlet.AsyncContext
      Dispatches the request to the resource at the specified path relative to the ServletContext from which this async request was started. After the dispatch, the async request processing is complete and the response is committed.
      Specified by:
      dispatch in interface AsyncContext
      Parameters:
      path - the path to which the request/response should be dispatched relative to the ServletContext from which this async request was started
    • dispatch

      public void dispatch(ServletContext servletContext, String path)
      Description copied from interface: jakarta.servlet.AsyncContext
      Dispatches the request to the resource at the specified path relative to the given ServletContext. After the dispatch, the async request processing is complete and the response is committed.
      Specified by:
      dispatch in interface AsyncContext
      Parameters:
      servletContext - the ServletContext to which the request/response should be dispatched
      path - the path to which the request/response should be dispatched relative to the specified ServletContext
    • getRequest

      public ServletRequest getRequest()
      Description copied from interface: jakarta.servlet.AsyncContext
      Returns the ServletRequest associated with this asynchronous operation.
      Specified by:
      getRequest in interface AsyncContext
      Returns:
      the ServletRequest object
    • getResponse

      public ServletResponse getResponse()
      Description copied from interface: jakarta.servlet.AsyncContext
      Returns the ServletResponse associated with this asynchronous operation.
      Specified by:
      getResponse in interface AsyncContext
      Returns:
      the ServletResponse object
    • start

      public void start(Runnable run)
      Description copied from interface: jakarta.servlet.AsyncContext
      Starts a new thread to process the asynchronous request
      Specified by:
      start in interface AsyncContext
      Parameters:
      run - a Runnable that the new thread will run
    • addListener

      public void addListener(AsyncListener listener)
      Description copied from interface: jakarta.servlet.AsyncContext
      Adds an event listener that will be called for different AsyncEvents fire
      Specified by:
      addListener in interface AsyncContext
      Parameters:
      listener - an AsyncListener that will be called with AsyncEvent objects
    • addListener

      public void addListener(AsyncListener listener, ServletRequest servletRequest, ServletResponse servletResponse)
      Description copied from interface: jakarta.servlet.AsyncContext
      Adds an event listener that will be called when different AsyncEvents fire
      Specified by:
      addListener in interface AsyncContext
      Parameters:
      listener - an AsyncListener that will be called with AsyncEvent objects
      servletRequest - the ServletRequest that will be passed with the AsyncEvent
      servletResponse - the ServletResponse that will be passed with the AsyncEvent
    • createListener

      public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException
      Description copied from interface: jakarta.servlet.AsyncContext
      Creates and returns an AsyncListener object
      Specified by:
      createListener in interface AsyncContext
      Type Parameters:
      T - The type to create that extends AsyncListener
      Parameters:
      clazz - The class to instantiate to create the listener
      Returns:
      the newly created AsyncListener object
      Throws:
      ServletException - if the listener cannot be created
    • recycle

      public void recycle()
      Recycles this async context, resetting all internal state for reuse.
    • isStarted

      public boolean isStarted()
      Checks whether async processing has been started for this context.
      Returns:
      true if async processing has started
    • setStarted

      public void setStarted(Context context, ServletRequest request, ServletResponse response, boolean originalRequestResponse)
      Initializes this async context with the given parameters and fires onStartAsync events.
      Parameters:
      context - The context for this async operation
      request - The servlet request
      response - The servlet response
      originalRequestResponse - true if the request/response are the original ones
    • hasOriginalRequestAndResponse

      public boolean hasOriginalRequestAndResponse()
      Description copied from interface: jakarta.servlet.AsyncContext
      Determines whether the request and response objects are the original ones passed to ServletRequest.startAsync(), or if they are new objects created by the container.
      Specified by:
      hasOriginalRequestAndResponse in interface AsyncContext
      Returns:
      true if the request and response are the original objects, false otherwise
    • doInternalDispatch

      protected void doInternalDispatch() throws ServletException, IOException
      Performs the internal dispatch for the pending async dispatch operation.
      Throws:
      ServletException - if a servlet error occurs
      IOException - if an I/O error occurs
    • getTimeout

      public long getTimeout()
      Description copied from interface: jakarta.servlet.AsyncContext
      Get the current timeout.
      Specified by:
      getTimeout in interface AsyncContext
      Returns:
      The timeout in milliseconds. 0 or less indicates no timeout.
    • setTimeout

      public void setTimeout(long timeout)
      Description copied from interface: jakarta.servlet.AsyncContext
      Set the timeout.
      Specified by:
      setTimeout in interface AsyncContext
      Parameters:
      timeout - The timeout in milliseconds. 0 or less indicates no timeout.
    • isAvailable

      public boolean isAvailable()
      Description copied from interface: AsyncContextCallback
      Reports if the web application associated with this async request is available.
      Specified by:
      isAvailable in interface AsyncContextCallback
      Returns:
      true if the associated web application is available, otherwise false
    • setErrorState

      public void setErrorState(Throwable t, boolean fireOnError)
      Sets the error state and optionally fires onError events to all registered listeners.
      Parameters:
      t - The throwable that caused the error, or null
      fireOnError - true if onError should be fired to listeners
    • incrementInProgressAsyncCount

      public void incrementInProgressAsyncCount()
      Description copied from interface: AsyncContextCallback
      Used to notify the Context that async processing has started. Specifically, for the counting of in-progress async requests to work correctly, this must be called exactly once every time the AsyncStateMachine transitions from DISPATCHED to any other state.
      Specified by:
      incrementInProgressAsyncCount in interface AsyncContextCallback
    • decrementInProgressAsyncCount

      public void decrementInProgressAsyncCount()
      Description copied from interface: AsyncContextCallback
      Used to notify the Context that async processing has ended. Specifically, for the counting of in-progress async requests to work correctly, this must be called exactly once every time the AsyncStateMachine transitions to DISPATCHED from any other state.
      Specified by:
      decrementInProgressAsyncCount in interface AsyncContextCallback