Top Description Inners Fields Constructors Methods
org.apache.catalina.valves

public Class PersistentValve

extends ValveBase
Class Inheritance
Imports
java.io.IOException, java.util.concurrent.ConcurrentHashMap, .ConcurrentMap, .Semaphore, java.util.concurrent.atomic.AtomicLong, java.util.regex.Pattern, .PatternSyntaxException, jakarta.servlet.ServletException, jakarta.servlet.http.HttpServletResponse, org.apache.catalina.Container, .Context, .Engine, .Globals, .Host, .Manager, .Session, .Store, .StoreManager, org.apache.catalina.connector.Request, .Response

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:

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static class

Field Summary

Modifier and TypeField and Description
private volatile boolean
protected Pattern
private static final ClassLoader
private boolean
private boolean
private boolean
private ConcurrentMap<String, PersistentValve.UsageCountingSemaphore>
Inherited from org.apache.catalina.valves.ValveBase:
asyncSupportedcontainercontainerLognextsm

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
private void
bind(Context context)

public String
public void
invoke(Request
Request to be processed
request
,
Response
Response to be produced
response
)

Implements org.apache.catalina.Valve.invoke.

Select the appropriate child Context to process this request, based on the specified request URI.

protected boolean
public boolean

Returns:

true if the thread can not be interrupted, otherwise false.
isSemaphoreAcquireUninterruptibly
()

If a thread is blocking to acquire a per session Semaphore, can that thread be interrupted?

public boolean

Returns:

true if the thread should block, otherwise false to reject the concurrent request
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?

public boolean

Returns:

true if fairness is enabled, otherwise false
isSemaphoreFairness
()

If multiple threads attempt to acquire the same per session Semaphore, will permits be granted in the same order they were requested?

protected boolean

Returns:

true if the session is past its expiration
isSessionStale
(Session
The session to check
session
,
long
The current time to check for
timeNow
)

Indicate whether the session has been idle for longer than its expiration date as of the supplied time.

protected void
onSemaphoreNotAcquired(Request
The request that will not be processed
request
,
Response
The response that will be used for this request
response
)

Handle the case where a semaphore cannot be obtained.

public void
setContainer(Container
The Container instance with which this instance is to be associated, or null to disassociate this instance from any Container
container
)

Overrides org.apache.catalina.valves.ValveBase.setContainer.

Implements org.apache.catalina.Contained.setContainer.

Set the Container with which this instance is associated.

public void
setFilter(String filter)

public void
setSemaphoreAcquireUninterruptibly(boolean
true if the thread can not be interrupted, otherwise false.
semaphoreAcquireUninterruptibly
)

Configure whether a thread blocking to acquire a per session Semaphore can be interrupted.

public void
setSemaphoreBlockOnAcquire(boolean
true to block, otherwise false
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.

public void
setSemaphoreFairness(boolean
true if permits should be granted in the same order they are requested, otherwise false
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.

private void
unbind(Context context)

Inherited from org.apache.catalina.valves.ValveBase:
backgroundProcessgetContainergetDomainInternalgetNextgetObjectNameKeyPropertiesinitInternalisAsyncSupportedsetAsyncSupportedsetNextstartInternalstopInternaltoString

Field Detail

clBindRequiredback to summary
private volatile boolean clBindRequired
filterback to summary
protected Pattern filter
MY_CLASSLOADERback to summary
private static final ClassLoader MY_CLASSLOADER
semaphoreAcquireUninterruptiblyback to summary
private boolean semaphoreAcquireUninterruptibly
semaphoreBlockOnAcquireback to summary
private boolean semaphoreBlockOnAcquire
semaphoreFairnessback to summary
private boolean semaphoreFairness
sessionToSemaphoreMapback to summary
private ConcurrentMap<String, PersistentValve.UsageCountingSemaphore> sessionToSemaphoreMap

Constructor Detail

PersistentValveback to summary
public PersistentValve()

Method Detail

bindback to summary
private void bind(Context context)
getFilterback to summary
public String getFilter()
invokeback to summary
public void invoke(Request request, Response response) throws IOException, ServletException

Implements org.apache.catalina.Valve.invoke.

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

Request to be processed

response:Response

Response to be produced

Annotations
@Override
Exceptions
IOException:
if an input/output error occurred
ServletException:
if a servlet error occurred
isRequestWithoutSessionback to summary
protected boolean isRequestWithoutSession(String uri)
isSemaphoreAcquireUninterruptiblyback to summary
public boolean isSemaphoreAcquireUninterruptibly()

If a thread is blocking to acquire a per session Semaphore, can that thread be interrupted?

Returns:boolean

true if the thread can not be interrupted, otherwise false.

isSemaphoreBlockOnAcquireback to summary
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:boolean

true if the thread should block, otherwise false to reject the concurrent request

isSemaphoreFairnessback to summary
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:boolean

true if fairness is enabled, otherwise false

isSessionStaleback to summary
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:Session

The session to check

timeNow:long

The current time to check for

Returns:boolean

true if the session is past its expiration

onSemaphoreNotAcquiredback to summary
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:Request

The request that will not be processed

response:Response

The response that will be used for this request

Exceptions
IOException:
If an I/O error occurs while working with the request or response
setContainerback to summary
public void setContainer(Container container)

Overrides org.apache.catalina.valves.ValveBase.setContainer.

Implements org.apache.catalina.Contained.setContainer.

Doc from org.apache.catalina.Contained.setContainer.

Set the Container with which this instance is associated.

Parameters
container:Container

The Container instance with which this instance is to be associated, or null to disassociate this instance from any Container

Annotations
@Override
setFilterback to summary
public void setFilter(String filter)
setSemaphoreAcquireUninterruptiblyback to summary
public void setSemaphoreAcquireUninterruptibly(boolean semaphoreAcquireUninterruptibly)

Configure whether a thread blocking to acquire a per session Semaphore can be interrupted.

Parameters
semaphoreAcquireUninterruptibly:boolean

true if the thread can not be interrupted, otherwise false.

setSemaphoreBlockOnAcquireback to summary
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:boolean

true to block, otherwise false

setSemaphoreFairnessback to summary
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:boolean

true if permits should be granted in the same order they are requested, otherwise false

unbindback to summary
private void unbind(Context context)
org.apache.catalina.valves back to summary

private Class PersistentValve.UsageCountingSemaphore

extends Object
Class Inheritance
  • java.lang.Object
  • org.apache.catalina.valves.PersistentValve.UsageCountingSemaphore

Field Summary

Modifier and TypeField and Description
private final Semaphore
private final AtomicLong

Constructor Summary

AccessConstructor and Description
private
UsageCountingSemaphore(boolean fairness)

Method Summary

Modifier and TypeMethod and Description
private void
private void
private long
private PersistentValve.UsageCountingSemaphore
private void
private boolean
Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

semaphoreback to summary
private final Semaphore semaphore
usageCountback to summary
private final AtomicLong usageCount

Constructor Detail

UsageCountingSemaphoreback to summary
private UsageCountingSemaphore(boolean fairness)

Method Detail

acquireback to summary
private void acquire() throws InterruptedException
acquireUninterruptiblyback to summary
private void acquireUninterruptibly()
decrementAndGetUsageCountback to summary
private long decrementAndGetUsageCount()
incrementUsageCountback to summary
private PersistentValve.UsageCountingSemaphore incrementUsageCount()
releaseback to summary
private void release()
tryAcquireback to summary
private boolean tryAcquire()