Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jetty 12.0.x object identity ee8 and ee9 #11888

Merged
merged 23 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
707371d
Possible fix for ee8/9 object identity
janbartel Jun 5, 2024
0015e45
Fix for sessions with cross context dispatches with object identity.
janbartel Jun 6, 2024
d4f52ad
Initial work for Cross Context Dispatch testing
joakime Jun 6, 2024
9fb467a
Update jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9…
janbartel Jun 11, 2024
7d26a14
Updates post review.
janbartel Jun 11, 2024
ba2c17e
Ensure cross context dispatch into ee8/ee9 has SessionStreamWrapper
janbartel Jun 11, 2024
456202e
Cleanup based on review
joakime Jun 11, 2024
7bab2e8
HttpSession plan
joakime Jun 11, 2024
9334394
More changes from review.
joakime Jun 12, 2024
8715015
Merge remote-tracking branch 'origin/fix/12.0.x/cross-context-testing…
janbartel Jun 12, 2024
6caa306
Fix re-dispatch back to ee8/9
janbartel Jun 12, 2024
6decc39
Testing for SessionCache .commit() and .release()
joakime Jun 12, 2024
175fff6
More session tests for ee10
joakime Jun 12, 2024
84457b4
Reenable test
joakime Jun 12, 2024
97f9df1
Merge remote-tracking branch 'origin/fix/12.0.x/cross-context-testing…
janbartel Jun 12, 2024
ff3ce62
Comment out disabling test.
janbartel Jun 12, 2024
79e996e
Merge remote-tracking branch 'origin/jetty-12.0.x' into fix/12.0.x/cr…
joakime Jun 14, 2024
976b432
Fix typos in SecurityHandler javadoc
janbartel Jun 18, 2024
898fa0f
Fixes for sessions after using cross-context dispatch tests.
janbartel Jun 18, 2024
044b9d9
Stopping forked server before testing session.log
joakime Jun 18, 2024
cce8d47
Remove printlns, fix test
janbartel Jun 19, 2024
554fae6
Merge remote-tracking branch 'origin/fix/12.0.x/cross-context-testing…
janbartel Jun 19, 2024
072fe8f
Merge remote-tracking branch 'origin/jetty-12.0.x' into jetty-12.0.x-…
janbartel Jun 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ public void setRefreshCookieAge(int ageInSeconds)
/**
* Get a known existing session
*
* @param extendedId The session id, possibly imcluding worker name suffix.
* @param extendedId The session id, possibly including worker name suffix.
* @return the Session matching the id or null if none exists
*/
@Override
Expand Down Expand Up @@ -1266,6 +1266,18 @@ protected RequestedSession resolveRequestedSessionId(Request request)
}
}

//try getting a session id for our context that has been newly created by another context
if (request.getContext().isCrossContextDispatch(request))
{
String tmp = (String)request.getAttribute(DefaultSessionIdManager.__NEW_SESSION_ID);
if (!StringUtil.isEmpty(tmp))
{
if (ids == null)
ids = new ArrayList<>();
ids.add(tmp);
}
}

if (ids == null)
return NO_REQUESTED_SESSION;

Expand Down Expand Up @@ -1425,7 +1437,8 @@ public HttpCookie getSessionCookie(ManagedSession session, boolean requestIsSecu

/**
* StreamWrapper to intercept commit and complete events to ensure
* session handling happens in context, with request available.
* session handling happens in context, with the request available.
* This implementation assumes that a request only has a single session.
*/
private class SessionStreamWrapper extends HttpStream.Wrapper
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,50 @@ public void testSessionCreateInvalidateCreate() throws Exception
}
}

@Test
public void testSessionCreateReForward() throws Exception
{
String contextPath = "";
String contextC = "/contextC";
String servletMapping = "/server";
int inactivePeriod = 20;
int scavengePeriod = 3;
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
cacheFactory.setFlushOnResponseCommit(true); //ensure session is saved before response comes back
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();

SessionTestSupport server1 = new SessionTestSupport(0, inactivePeriod, scavengePeriod, cacheFactory, storeFactory);
TestServlet servlet = new TestServlet();
ServletHolder holder = new ServletHolder(servlet);
ServletContextHandler contextHandler = server1.addContext(contextPath);
contextHandler.setCrossContextDispatchSupported(true);
contextHandler.addServlet(holder, servletMapping);
ServletContextHandler ctxC = server1.addContext(contextC);
ctxC.setCrossContextDispatchSupported(true);
ctxC.addServlet(TestServletC.class, servletMapping);
server1.start();
int port1 = server1.getPort();

try (StacklessLogging stackless = new StacklessLogging(CreationTest.class.getPackage()))
{
HttpClient client = new HttpClient();
client.start();
String url = "http://localhost:" + port1 + contextPath + servletMapping;

ContentResponse response = client.GET(url + "?action=forwardC");
assertEquals(HttpServletResponse.SC_OK, response.getStatus());

//check that the sessions exist persisted
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> contextHandler.getSessionHandler().getSessionCache().getSessionDataStore().exists(servlet._id));
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> ctxC.getSessionHandler().getSessionCache().getSessionDataStore().exists(servlet._id));
}
finally
{
server1.stop();
}
}

/**
* Create a session in a context, forward to another context and create a
* session in it too. Check that both sessions exist after the response
Expand Down Expand Up @@ -426,84 +470,99 @@ public void setStore(SessionDataStore store)
protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
String action = request.getParameter("action");

if (action != null && action.startsWith("forward"))
switch (action.toLowerCase())
{
HttpSession session = request.getSession(true);

_id = session.getId();
session.setAttribute("value", 1);

ServletContext contextB = getServletContext().getContext("/contextB");
RequestDispatcher dispatcherB = contextB.getRequestDispatcher(request.getServletPath());
dispatcherB.forward(request, httpServletResponse);

if (action.endsWith("inv"))
{
session.invalidate();
}
else
case "forward" ->
{
HttpSession session = createAndSaveSessionId(request);
ServletContext contextB = getServletContext().getContext("/contextB");
RequestDispatcher dispatcherB = contextB.getRequestDispatcher(request.getServletPath());
dispatcherB.forward(request, httpServletResponse);

session = request.getSession(false);
assertNotNull(session);
assertEquals(_id, session.getId());
assertNotNull(session.getAttribute("value"));
assertNull(session.getAttribute("B")); //check we don't see stuff from other context
}
return;
}
else if ("test".equals(action))
{
HttpSession session = request.getSession(false);
assertNotNull(session);
return;
}
else if (action != null && action.startsWith("create"))
{
currentRequest.set(request);
HttpSession session = request.getSession(true);
_id = session.getId();
session.setAttribute("value", 1);

System.err.println("Created session " + _id);
String check = request.getParameter("check");
if (!StringUtil.isBlank(check) && _store != null)
case "forwardc" ->
{
boolean exists;
try
{
exists = _store.exists(_id);
System.err.println("Does session exist in store: " + exists);
}
catch (Exception e)
{
throw new ServletException(e);
}
HttpSession session = createAndSaveSessionId(request);

if ("false".equalsIgnoreCase(check))
assertFalse(exists);
else
assertTrue(exists);
//forward to contextC
ServletContext contextC = getServletContext().getContext("/contextC");
RequestDispatcher dispatcherC = contextC.getRequestDispatcher(request.getServletPath());
dispatcherC.forward(request, httpServletResponse);
}

if ("createinv".equals(action))
case "forwardinv" ->
{
session.invalidate();
assertNull(request.getSession(false));
HttpSession session = createAndSaveSessionId(request);
assertNotNull(session);

ServletContext contextB = getServletContext().getContext("/contextB");
RequestDispatcher dispatcherB = contextB.getRequestDispatcher(request.getServletPath());
dispatcherB.forward(request, httpServletResponse);
session.invalidate();
}
else if ("createinvcreate".equals(action))
case "test" ->
{
session.invalidate();
System.err.println("Session invalidated " + _id);
assertNull(request.getSession(false));
assertNotNull(_id);
HttpSession session = request.getSession(false);
assertNotNull(session);
session = request.getSession(true);
_id = session.getId();
System.err.println("Created another session " + _id);
assertNotNull(session.getAttribute("value")); //check we see our previous session
assertNull(session.getAttribute("B")); //check we don't see stuff from other contexts
assertNull(session.getAttribute("C"));
}
case "create", "createinv", "createinvcreate" ->
{
currentRequest.set(request);
HttpSession session = createAndSaveSessionId(request);
String check = request.getParameter("check");
if (!StringUtil.isBlank(check) && _store != null)
{
boolean exists = false;
try
{
exists = _store.exists(_id);
}
catch (Exception e)
{
throw new ServletException(e);
}

switch (check.toLowerCase())
{
case "true" -> assertTrue(exists);
case "false" -> assertFalse(exists);
}
}

if ("createinv".equals(action))
{
session.invalidate();
assertNull(request.getSession(false));
assertNotNull(session);
}
else if ("createinvcreate".equals(action))
{
session.invalidate();

assertNull(request.getSession(false));
assertNotNull(session);
session = request.getSession(true);
_id = session.getId();
}
}
}
}

private HttpSession createAndSaveSessionId(HttpServletRequest request)
{
HttpSession session = request.getSession(true);
_id = session.getId();
session.setAttribute("value", 1);
return session;
}
}

public static class TestServletB extends HttpServlet
Expand All @@ -525,4 +584,25 @@ protected void doGet(HttpServletRequest request, HttpServletResponse httpServlet
session.setAttribute("B", "B");
}
}

public static class TestServletC extends HttpServlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
HttpSession session = request.getSession(false);
assertNull(session);
session = request.getSession(true);

// Be sure nothing from contextA is present
Object objectA = session.getAttribute("value");
assertNull(objectA);

session.setAttribute("C", "C");

//forward back to A
ServletContext contextA = getServletContext().getContext("/");
RequestDispatcher dispatcherA = contextA.getRequestDispatcher(request.getServletPath() + "?action=test");
dispatcherA.forward(request, httpServletResponse);
}
}
}
Loading
Loading