From 49ac6de01126a437ee9678d6e10a2ae5836a0d2a Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Mon, 20 Jan 2014 13:28:50 +1100 Subject: [PATCH] 425930 JDBC Session Manager constantly reloading session if save intervall expired once --- .../server/session/JDBCSessionManager.java | 7 +- .../server/session/SaveIntervalTest.java | 179 ++++++++++++++++++ 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SaveIntervalTest.java diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java index 4a11552fec0..e48a3b61303 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java @@ -495,6 +495,7 @@ public class JDBCSessionManager extends AbstractSessionManager " interval="+(_saveIntervalSec * 1000L)); else LOG.debug("getSession("+idInCluster+"): in session map, "+ + " hashcode="+memSession.hashCode()+ " now="+now+ " lastSaved="+(memSession==null?0:memSession._lastSaved)+ " interval="+(_saveIntervalSec * 1000L)+ @@ -566,7 +567,11 @@ public class JDBCSessionManager extends AbstractSessionManager } else + { + //the session loaded from the db and the one in memory are the same, so keep using the one in memory + session = memSession; LOG.debug("getSession({}): Session not stale {}", idInCluster,session); + } } else { @@ -1100,7 +1105,7 @@ public class JDBCSessionManager extends AbstractSessionManager data.setLastSaved(now); } if (LOG.isDebugEnabled()) - LOG.debug("Updated access time session id="+data.getId()); + LOG.debug("Updated access time session id="+data.getId()+" with lastsaved="+data.getLastSaved()); } diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SaveIntervalTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SaveIntervalTest.java new file mode 100644 index 00000000000..d965d687841 --- /dev/null +++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SaveIntervalTest.java @@ -0,0 +1,179 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server.session; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.junit.Test; +import org.junit.Ignore; + +/** + * SaveIntervalTest + * + * Checks to see that potentially stale sessions that have not + * changed are not always reloaded from the datase. + * + * This test is Ignored because it takes a little while to run. + * + */ +public class SaveIntervalTest +{ + public static int INACTIVE = 90; //sec + public static int SCAVENGE = 100; //sec + public static int SAVE = 10; //sec + + + @Ignore + @Test + public void testSaveInterval() throws Exception + { + AbstractTestServer server = new JdbcTestServer(0,INACTIVE,SCAVENGE); + + ServletContextHandler ctxA = server.addContext("/mod"); + ServletHolder holder = new ServletHolder(); + TestSaveIntervalServlet servlet = new TestSaveIntervalServlet(); + holder.setServlet(servlet); + ctxA.addServlet(holder, "/test"); + ((JDBCSessionManager)ctxA.getSessionHandler().getSessionManager()).setSaveInterval(SAVE); + server.start(); + int port=server.getPort(); + try + { + HttpClient client = new HttpClient(); + client.start(); + try + { + // Perform a request to create a session + ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create"); + assertEquals(HttpServletResponse.SC_OK,response.getStatus()); + String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); + assertTrue(sessionCookie != null); + // Mangle the cookie, replacing Path with $Path, etc. + sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); + long lastSaved = ((JDBCSessionManager.Session)servlet._session).getLastSaved(); + + + //do another request to change the session attribute + Request request = client.newRequest("http://localhost:" + port + "/mod/test?action=set"); + request.header("Cookie", sessionCookie); + response = request.send(); + assertEquals(HttpServletResponse.SC_OK,response.getStatus()); + long tmp = ((JDBCSessionManager.Session)servlet._session).getLastSaved(); + assertNotEquals(lastSaved, tmp); //set of attribute will cause save to db + lastSaved = tmp; + + //do nothing for just a bit longer than the save interval to ensure + //session will be checked against database on next request + Thread.currentThread().sleep((SAVE+2)*1000); + + + //do another request to access the session, this will cause session to be initially + //checked against db. On exit of request, the access time will need updating, so the + //session will be saved to db. + request = client.newRequest("http://localhost:" + port + "/mod/test?action=tickle"); + request.header("Cookie", sessionCookie); + response = request.send(); + assertEquals(HttpServletResponse.SC_OK,response.getStatus()); + tmp = ((JDBCSessionManager.Session)servlet._session).getLastSaved(); + assertNotEquals(lastSaved, tmp); + lastSaved = tmp; + + //wait a little and do another request to access the session + Thread.currentThread().sleep((SAVE/2)*1000); + + //do another request to access the session. This time, the save interval has not + //expired, so we should NOT see a debug trace of loading stale session. Nor should + //the exit of the request cause a save of the updated access time. + request = client.newRequest("http://localhost:" + port + "/mod/test?action=tickle"); + request.header("Cookie", sessionCookie); + response = request.send(); + assertEquals(HttpServletResponse.SC_OK,response.getStatus()); + tmp = ((JDBCSessionManager.Session)servlet._session).getLastSaved(); + assertEquals(lastSaved, tmp); //the save interval did not expire, so update to the access time will not have been persisted + } + finally + { + client.stop(); + } + } + finally + { + server.stop(); + } + } + + public static class TestSaveIntervalServlet extends HttpServlet + { + public HttpSession _session; + + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + String action = request.getParameter("action"); + + + if ("create".equals(action)) + { + HttpSession session = request.getSession(true); + System.err.println("CREATE: Session id="+session.getId()); + _session = session; + return; + } + + if ("set".equals(action)) + { + HttpSession session = request.getSession(false); + if (session == null) + throw new ServletException("Session is null for action=change"); + + System.err.println("SET: Session id="+session.getId()); + session.setAttribute("aaa", "12345"); + assertEquals(_session.getId(), session.getId()); + return; + } + + if ("tickle".equals(action)) + { + HttpSession session = request.getSession(false); + if (session == null) + throw new ServletException("Session does not exist"); + System.err.println("TICKLE: Session id="+session.getId()); + assertEquals(_session.getId(), session.getId()); + return; + } + } + } + +}