Class AsyncContextImpl

  • All Implemented Interfaces:
    AsyncContext, AsyncContextCallback

    public class AsyncContextImpl
    extends java.lang.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 Detail

      • sm

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

      • AsyncContextImpl

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

      • 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​(java.lang.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,
                             java.lang.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
      • start

        public void start​(java.lang.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​(java.lang.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
      • doInternalDispatch

        protected void doInternalDispatch()
                                   throws ServletException,
                                          java.io.IOException
        Performs the internal dispatch for the pending async dispatch operation.
        Throws:
        ServletException - if a servlet error occurs
        java.io.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​(java.lang.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