blogger templates blogger widgets
This is part of a list of blog posts.
To browse the contents go to

Sharing JSESSIONID across applications on server


For a quick look into the basics of JSESSIONID have a look here.

Why would we need to share JSESSIONID or any data across web applications within the same container(jvm)?

For small scale applications this wouldn't come as a necessity but as the applications grow and Modularity steps in. For eg: we would create separate projects for login/logout module and business logic module.

There are a number of ways you could do this - letting both applications share by reading and writing to a external database or cache, JMS, etc. But all these approaches are a overhead if you just need to share JSESSIONID and few variables related to that specific session.

I present 2 approaches on tomcat container.

- Programmatically managed
- Container managed

Before we start, create 2 web applications - AppOne and AppTwo.

index.jsp in AppOne


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>
<%@ page import="java.util.Map"%>
<%@ page import="java.util.HashMap"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Index page</title>
</head>
<body>
 <form method="post" action="index.jsp">
<input type="text" name="in" /> <input type="submit" value="submit" />
 </form>
<%
  String inputdata = null;
  String cookieFromRequestHeader = request.getHeader("cookie");
  //in-coming cookie to server
  System.out.println("incoming cookie: "+cookieFromRequestHeader);
  inputdata = request.getParameter("in");
  System.out.println(inputdata); 
  if (inputdata != null) {
   session.setAttribute("a", inputdata);
  }
  //out-going cookie from server
  String cookieFromResponseHeader = response.getHeader("Set-Cookie");
  System.out.println("outgoing cookie: "+cookieFromResponseHeader);
 %>
 <a href="one.jsp">One</a>
<a href="/AppTwo/two.jsp">Two</a>
</body>
</html>

one.jsp in AppOne


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="java.util.Map" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="UTF-8">
<title>Page One</title>
</head>
<body>
<% 
String cookieFromRequestHeader = request.getHeader("cookie"); 
%>
Session Id: <%= request.getSession().getId() %>
Session attr 'a' : <%=request.getSession().getAttribute("a")%>
Cookie from request: <%= cookieFromRequestHeader %>
</body>
</html>

two.jsp in AppTwo


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="java.util.Map" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Page Two</title>
</head>
<body>
<% 
String cookieFromRequestHeader = request.getHeader("cookie");
%>
Session Id: <%= request.getSession().getId() %>
Session attr 'a' : <%=request.getSession().getAttribute("a")%>
Cookie from request: <%= cookieFromRequestHeader %>
</body>
</html>

One both the applications are deployed on the server, hit http://localhost:8080/AppOne/index.jsp

System.out logs,
incoming cookie: null
null
outgoing cookie: JSESSIONID=B2AA271E701283A482F588F7EC8E1A34; Path=/AppOne/; HttpOnly

If you check the browser debugger console, you will notice the jsessionID set in the response headers from server
Set-Cookie: JSESSIONID=B2AA271E701283A482F588F7EC8E1A34; Path=/AppOne/; HttpOnly

Hitting the same url again,
incoming cookie: JSESSIONID=B2AA271E701283A482F588F7EC8E1A34
hello
outgoing cookie: null

Note that the server doesn't send the jsessionID every time to the client as that's unnecessary. The server maintains the sessionId within it's internal map and check if the incoming request has a session Id from that Map, Else it creates a new one and sends it.

If you check the browser debugger console, you will notice the jsessionID set in the request headers from browser
Cookie: JSESSIONID=B2AA271E701283A482F588F7EC8E1A34
Referer: http://localhost:8080/AppOne/index.jsp
Origin: http://localhost:8080



http://localhost:8080/AppOne/one.jsp

Session Id: B2AA271E701283A482F588F7EC8E1A34
Session attr 'a' : hello
Cookie from request: JSESSIONID=B2AA271E701283A482F588F7EC8E1A34

http://localhost:8080/AppTwo/two.jsp

Session Id: 244C198FC0BAF8981C0634A6BB56704E
Session attr 'a' : null
Cookie from request: null

As seen, the JSESSIONID are different for pages originating from different contexts, /AppOne and /AppTwo in our case.



Setting the sessionCookiePath

Setting the same sessionCookiePath for individual applications enables the sessionID to be set at this given context path level.

There are 3 ways you could do this.

  1. Server level
  2. In tomcat's server.xml add sessionCookiePath for all necessary applications
    
    <context sessionCookiePath="/" docBase="AppOne" path="/AppOne" reloadable="true" source="org.eclipse.jst.jee.server:AppOne"/>
    <context sessionCookiePath="/" docBase="AppTwo" path="/AppTwo" reloadable="true" source="org.eclipse.jst.jee.server:AppTwo"/>
    
  3. Application level
  4. Declaratively add the following to the web.xml:
    
    <session-config>
        <cookie-config>
            <path>/</path>
        </cookie-config>
    </session-config>
    
  5. Program level
  6. Use SessionCookieConfig which is available by
    
    getServletContext().getSessionCookieConfig().setPath("/");
    

I tried with the first option and it worked.




No comments:

Post a Comment