EAP 8.1 skips session lock and allows concurrent requests for individual session

Solution Verified - Updated

Environment

  • JBoss Enterprise Application Platform (EAP) 8.1.x

Issue

  • After upgrading from EAP 8.0 to 8.1, sessions are not being locked as expected with a web cache configuration like below:
                <distributed-cache name="dist">
                    <locking isolation="REPEATABLE_READ"/>
                    <transaction mode="BATCH"/>
                    <expiration interval="0"/>
                    <file-store passivation="true" purge="true"/>
                </distributed-cache>
  • Sessions are now being concurrently accessed and modified through multiple requests at a time on EAP 8.1 to result in unexpected behaviors and session state conflicts

Resolution

This is working as intended.
Locking sessions per request was not a true goal of the prior implementation in EAP 8.0 (and even earlier), but rather a consequence of ensuring that the state of a session was consistent with a previous request (in particular, when the previous request was serviced by a different cluster member). EAP 8.1+ no longer has this limitation provided that the previous request was handled by the same cluster member. Concurrent requests to the same server can now safely access a session (in the same way as a non-distributed session manager would) without sacrificing consistency.
Therefore, it is now expected that this lock is obtained only on the first concurrent request and then shared by all concurrently executing requests for a given session within a single JVM (requests that would then appear to skip over the typical lock acquisition from CacheStrategy$2$1.computeIfAbsent) and only released when the last concurrent request completes.

Thus the application itself should ensure the thread safety of its own request processing logic and any objects (as a part of session attributes or not) it uses within that as detailed in Content from jakarta.ee is not included.Jakarta servlet specification.

For a shorter term solution to avoid application thread safety issues by enforcing a similar limit on request concurrency for a given session on EAP 8.1 as on EAP 8.0 and earlier, an application level filter like below could be used (or provide such a filter to the server config to apply all apps through a global module:

@WebFilter
public SynchronizedSessionFilter implements Filter {
  @Override
  public void doFilter​(ServletRequest request, ServletResponse response, FilterChain chain) {
    if (request instanceof HttpServletRequest httpRequest) {
      HttpSession session = httpRequest.getSession(false);
      if (session != null) {
        synchronized (session) {
          chain.doFilter(request, response);
        }
      }
    }
  }
}

Root Cause

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.