Handle async cross context session completion
This commit is contained in:
Greg Wilkins 2018-12-18 16:00:46 +11:00
parent 06bbab50f9
commit 503bd71d4c
2 changed files with 24 additions and 15 deletions

View File

@ -1611,7 +1611,7 @@ public class SessionHandler extends ScopedHandler
@Override @Override
public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{ {
SessionHandler old_session_manager = null; SessionHandler old_session_handler = null;
HttpSession old_session = null; HttpSession old_session = null;
HttpSession existingSession = null; HttpSession existingSession = null;
@ -1620,10 +1620,10 @@ public class SessionHandler extends ScopedHandler
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("SessionHandler.doScope"); LOG.debug("SessionHandler.doScope");
old_session_manager = baseRequest.getSessionHandler(); old_session_handler = baseRequest.getSessionHandler();
old_session = baseRequest.getSession(false); old_session = baseRequest.getSession(false);
if (old_session_manager != this) if (old_session_handler != this)
{ {
// new session context // new session context
baseRequest.setSessionHandler(this); baseRequest.setSessionHandler(this);
@ -1634,7 +1634,7 @@ public class SessionHandler extends ScopedHandler
// access any existing session for this context // access any existing session for this context
existingSession = baseRequest.getSession(false); existingSession = baseRequest.getSession(false);
if ((existingSession != null) && (old_session_manager != this)) if ((existingSession != null) && (old_session_handler != this))
{ {
HttpCookie cookie = access(existingSession,request.isSecure()); HttpCookie cookie = access(existingSession,request.isSecure());
// Handle changed ID or max-age refresh, but only if this is not a redispatched request // Handle changed ID or max-age refresh, but only if this is not a redispatched request
@ -1656,13 +1656,17 @@ public class SessionHandler extends ScopedHandler
{ {
//if there is a session that was created during handling this context, then complete it //if there is a session that was created during handling this context, then complete it
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("FinalSession={}, old_session_manager={}, this={}, calling complete={}", baseRequest.getSession(false), old_session_manager, this, (old_session_manager != this)); LOG.debug("FinalSession={}, old_session_handler={}, this={}, calling complete={}", baseRequest.getSession(false), old_session_handler, this, (old_session_handler != this));
if (old_session_manager != this)
// If we are leaving the scope of this session handler, ensure the session is completed
if (old_session_handler != this)
ensureCompletion(baseRequest); ensureCompletion(baseRequest);
if (old_session_manager != null && old_session_manager != this) // revert the session handler to the previous, unless it was null, in which case remember it as
// the first session handler encountered.
if (old_session_handler != null && old_session_handler != this)
{ {
baseRequest.setSessionHandler(old_session_manager); baseRequest.setSessionHandler(old_session_handler);
baseRequest.setSession(old_session); baseRequest.setSession(old_session);
} }
} }

View File

@ -52,22 +52,20 @@ import org.junit.jupiter.api.Test;
*/ */
public class AsyncTest public class AsyncTest
{ {
public static class LatchServlet extends HttpServlet public static class LatchServlet extends HttpServlet
{ {
@Override @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{ {
resp.getWriter().println("Latched"); resp.getWriter().println("Latched");
} }
} }
@Test @Test
public void testSessionWithAsyncDispatch() throws Exception public void testSessionWithAsyncDispatch() throws Exception
{ {
// Test async dispatch back to same context, which then creates a session.
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory(); DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT); cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT);
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory(); SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
@ -118,6 +116,8 @@ public class AsyncTest
@Test @Test
public void testSessionWithAsyncComplete() throws Exception public void testSessionWithAsyncComplete() throws Exception
{ {
// Test async write, which creates a session and completes outside of a dispatch
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory(); DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT); cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT);
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory(); SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
@ -168,6 +168,9 @@ public class AsyncTest
@Test @Test
public void testSessionWithCrossContextAsync() throws Exception public void testSessionWithCrossContextAsync() throws Exception
{ {
// Test async dispatch from context A to context B then
// async dispatch back to context B, which then creates a session (in context B).
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory(); DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT); cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT);
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory(); SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
@ -218,10 +221,13 @@ public class AsyncTest
} }
} }
@Test @Test
public void testSessionWithCrossContextAsyncComplete() throws Exception public void testSessionWithCrossContextAsyncComplete() throws Exception
{ {
// Test async dispatch from context A to context B, which then does an
// async write, which creates a session (in context A) and completes outside of a
// dispatch
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory(); DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT); cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT);
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory(); SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
@ -240,7 +246,6 @@ public class AsyncTest
ServletHolder latchHolder = new ServletHolder(latchServlet); ServletHolder latchHolder = new ServletHolder(latchServlet);
contextB.addServlet(latchHolder, "/latch"); contextB.addServlet(latchHolder, "/latch");
server.start(); server.start();
int port = server.getPort(); int port = server.getPort();