Engineering Full Stack Apps with Java and JavaScript
In Java EE, a session between a client and server may be maintained in three different ways: cookies, url rewriting and SSL sessions. We will see both session management through cookies and URL rewriting here. In both these approaches multiple requests from the client are connected together as a session using an attribute JSESSIONID. In case of session management through cookies, a cookie with name JSESSIONID saves the JSESSIONID at client (browser) side and is sent to client every time a request is made within that session from that same client. In session management through URL encoding, JSESSIONID is sent by client as part of the URL for every request made to server within that session from that same client.
Session management through cookies is supported by default by Java EE containers like Tomcat, whereas you need to encode your URLs with the JSESSION ID of the session to use url encoding. Both approaches have their advantage and disadvantage. Advantages with cookies are that it is supported by default by Java EE containers, and does not have url breakage errors like that of URL rewriting. However a browser may disable cookies for security and privacy reasons, in which case, session management through cookies will not work. Advantage of URL rewriting is that it will work even if cookies are disabled. However client will need to send the URL with JSESSIONID every time and if JSESSIONID is not present in the URL, then it will be treated as a new session.
Using response object’ encodeURL and sendRedirectEncodeURL methods to encode JSESSIONID to our URLs we can combine session management approach with cookies and session management through URL rewriting. We can construct the url and encode using either of these methods so that only when cookies are disabled, the JSESSIONID will be added. The sendRedirectEncodeURL will also make sure that if a redirect is made to an url outside current web application, JSESSIONID is not added.
We will first create a util class with some utility methods that use the APIs provided by Java EE to demonstrate various aspects of session management. We will then use these utility methods in a session management scenario involving two servlets.
Method 1 – checkAndPrintIfSessionIsNew
This method will check if a session is new using the Session object’s isNew method and print appropriate message into the response stream.
public static void checkAndPrintIfSessionIsNew(HttpServletRequest request,
HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
if (session.isNew()) {
out.println("<h2>This is a new session!!!</h2>");
} else {
out.println("<h2>You are still in same session!!!</h2>");
}
}
Method 2 – checkCookiesAndPrintJSESSIONID
This method will check if there is a cookie with the name JSESSIONID and if present will print its values, and if not present will print appropriate message into the response stream.
public static void checkCookiesAndPrintJSESSIONID(HttpServletRequest request,
HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
Cookie[] cookies = request.getCookies();
if (cookies != null) {
boolean cookieJSESSIONIDFound = false;
for (Cookie cookie : cookies) {
if (cookie.getName().equals("JSESSIONID")) {
cookieJSESSIONIDFound = true;
out.print("<h2>Cookie with name JSESSIONID found!</h2>");
out.println("JSESSIONID=" + cookie.getValue());
}
}
if (!cookieJSESSIONIDFound) {
out.print("<br><h2>Cookie with name JSESSIONID NOT found!</h2>");
}
}
}
Method 3 – printSessionRelatedRequestMethods
Request object contains few methods which can provide information about the session management. This method will print the current values of those methods into the reponse stream.
public static void printSessionRelatedRequestMethods(
HttpServletRequest request, HttpServletResponse response)
throws IOException {
PrintWriter out = response.getWriter();
out.print("<h2>Session related methods in request object</h2>");
out.print("request.getRequestedSessionId()="
+ request.getRequestedSessionId());
out.print("<br>request.isRequestedSessionIdFromCookie()="
+ request.isRequestedSessionIdFromCookie());
out.print("<br>request.isRequestedSessionIdFromURL()="
+ request.isRequestedSessionIdFromURL());
out.print("<br>request.isRequestedSessionIdValid()="
+ request.isRequestedSessionIdValid());
}
Method 4 – printURLsAndNavigationLink
This method will create the URL for navigating to the other servlet. Initially we will create the normal URL and we will then encode it. There will be two navigational links, one using encoding and one without encoding, so that we can see the difference.
public static void printURLsAndNavigationLink(HttpServletRequest request,
HttpServletResponse response, String next, String label)
throws IOException {
PrintWriter out = response.getWriter();
String URL = request.getContextPath() + next;
String encodedURL = response.encodeURL(URL);
out.print("<h2>URLs</h2>");
out.print("Original URL=" + URL);
out.print("<br>Encoded URL=" + encodedURL);
out.print("<br><br><a href=\"" + URL + "\">" + label + "(No Encoding)</a>");
out.print("<br><br><a href=\"" + encodedURL + "\">" + label + "(Encoded)</a>");
}
We will now call these methods from our two servlets – FirstServlet and SecondServlet.
FirstServlet’s doGet method
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpUtil.checkAndPrintIfSessionIsNew(request, response);
HttpUtil.checkCookiesAndPrintJSESSIONID(request, response);
HttpUtil.printSessionRelatedRequestMethods(request, response);
HttpUtil.printURLsAndNavigationLink(request, response, "/SecondServlet",
"Go Next");
}
SecondServlet’s doGet method
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpUtil.checkAndPrintIfSessionIsNew(request, response);
HttpUtil.checkCookiesAndPrintJSESSIONID(request, response);
HttpUtil.printSessionRelatedRequestMethods(request, response);
HttpUtil.printURLsAndNavigationLink(request, response, "/FirstServlet",
"Go Back");
}
Case 1: Cookies are enabled
Loading the FirstServlet will provide below output:
Now click Go Next (No Encoding) to go to SecondServlet and you can see that you are still in session. You will get the same response if you had clicked the encoded url also, as in this case both are same are cookies are enabled.
If you click Go Back (Encoded or Not Encoded), you will get the FirstServlet and you can see that you are still in session.
Case 2: Cookies disabled.
You can disable cookie in Mozilla as https://support.mozilla.org/en-US/kb/enable-and-disable-cookies-website-preferences.
You can see that you are in a new session and all session related methods are null or false. If you navigate to next and then back using the url which is not encoded, you will get similar response. Every time it will be new session if you navigate through normal url without encoding..
You can also see that encoded url now has jsession id added to it as cookies are disabled. If you click the encoded url version, you will remain in session and also sessionIdFromURL will return true (Previously when cookies were enabled, sessionIdFromCookie was returning true).