Class PersistentValve

  • All Implemented Interfaces:
    MBeanRegistration, Contained, JmxEnabled, Lifecycle, Valve

    public class PersistentValve
    extends ValveBase
    Valve that implements per-request session persistence. It is intended to be used with non-sticky load-balancers and a PersistentManager. The Valve works by loading the session from the Store at the start of the request, the request then updates the session as required and the Valve saves the session to the Store at the end of the request.

    To avoid conflicts and/or errors when updating the session store, each session must only be accessed by no more than one concurrent request. The filter field can be used to define requests (e.g. those for static resources) that do not need access to the session and can Requests for resources that do not need to access the session and can bypass the session load/save functionality provided by this Valve.

    The Valve uses a per session Semaphore to ensure that each session is accessed by no more than one request at a time within a single Tomcat instance. The behaviour if multiple requests try to access the session concurrently can be controlled by the semaphoreFairness, semaphoreBlockOnAcquire and semaphoreAcquireUninterruptibly fields. If a request fails to obtain the Semaphore, the response is generated by the onSemaphoreNotAcquired(Request, Response) method which, by default, returns a 429 status code.

    The per session Semaphores only provide limited protection against concurrent requests within a single Tomcat instance. If multiple requests access the same session concurrently across different Tomcat instances, update conflicts and/or session data loss and/or errors are very likely.

    USAGE CONSTRAINTS:

    • This Valve must only be used with a PersistentManager
    • The client must ensure that no more than one concurrent request accesses a session at any time across all Tomcat instances
    • Field Detail

    • Constructor Detail

      • PersistentValve

        public PersistentValve()
    • Method Detail

      • setContainer

        public void setContainer​(Container container)
        Description copied from interface: Contained
        Set the Container with which this instance is associated.
        Specified by:
        setContainer in interface Contained
        Overrides:
        setContainer in class ValveBase
        Parameters:
        container - The Container instance with which this instance is to be associated, or null to disassociate this instance from any Container
      • invoke

        public void invoke​(Request request,
                           Response response)
                    throws IOException,
                           ServletException
        Select the appropriate child Context to process this request, based on the specified request URI. If no matching Context can be found, return an appropriate HTTP error.
        Parameters:
        request - Request to be processed
        response - Response to be produced
        Throws:
        IOException - if an input/output error occurred
        ServletException - if a servlet error occurred
      • onSemaphoreNotAcquired

        protected void onSemaphoreNotAcquired​(Request request,
                                              Response response)
                                       throws IOException
        Handle the case where a semaphore cannot be obtained. The default behaviour is to return a 429 (too many requests) status code.
        Parameters:
        request - The request that will not be processed
        response - The response that will be used for this request
        Throws:
        IOException - If an I/O error occurs while working with the request or response
      • isSessionStale

        protected boolean isSessionStale​(Session session,
                                         long timeNow)
        Indicate whether the session has been idle for longer than its expiration date as of the supplied time.
        Parameters:
        session - The session to check
        timeNow - The current time to check for
        Returns:
        true if the session is past its expiration
      • isRequestWithoutSession

        protected boolean isRequestWithoutSession​(String uri)
      • getFilter

        public String getFilter()
      • setFilter

        public void setFilter​(String filter)
      • isSemaphoreFairness

        public boolean isSemaphoreFairness()
        If multiple threads attempt to acquire the same per session Semaphore, will permits be granted in the same order they were requested?
        Returns:
        true if fairness is enabled, otherwise false
      • setSemaphoreFairness

        public void setSemaphoreFairness​(boolean semaphoreFairness)
        Configure whether the per session Semaphores will handle granting of permits in the same order they were requested if multiple threads attempt to acquire the same Semaphore.
        Parameters:
        semaphoreFairness - true if permits should be granted in the same order they are requested, otherwise false
      • isSemaphoreBlockOnAcquire

        public boolean isSemaphoreBlockOnAcquire()
        If a thread attempts to acquire the per session Semaphore while it is being used by another request, should the thread block to wait for the Semaphore or should the request be rejected?
        Returns:
        true if the thread should block, otherwise false to reject the concurrent request
      • setSemaphoreBlockOnAcquire

        public void setSemaphoreBlockOnAcquire​(boolean semaphoreBlockOnAcquire)
        Configure whether a thread should block and wait for the per session Semaphore or reject the request if the Semaphore is being used by another request.
        Parameters:
        semaphoreBlockOnAcquire - true to block, otherwise false
      • isSemaphoreAcquireUninterruptibly

        public boolean isSemaphoreAcquireUninterruptibly()
        If a thread is blocking to acquire a per session Semaphore, can that thread be interrupted?
        Returns:
        true if the thread can not be interrupted, otherwise false.
      • setSemaphoreAcquireUninterruptibly

        public void setSemaphoreAcquireUninterruptibly​(boolean semaphoreAcquireUninterruptibly)
        Configure whether a thread blocking to acquire a per session Semaphore can be interrupted.
        Parameters:
        semaphoreAcquireUninterruptibly - true if the thread can not be interrupted, otherwise false.