11.1 Overview
A session is a conversation between the server and a client .We all know that HTTP protocol is a stateless protocol which means no user information is pertained and server considers every request as a new request.
Why do we need session tracking? Think of the scenario where a series of request and response takes place between same client and a server (for example online shopping system ) so to maintain the conversational state , session tracking is needed.
11.2 Techniques
Basically there are four techniques which can be used to identify a user session.
- Cookies
- Hidden Fields
- URL Rewriting
- Session Tracking API
Cookies , Hidden Fields and URL rewriting involves sending a unique identifier with each request and servlets determines the user session based on the identifier. Session API uses the other three techniques internally and provides a session tracking in much convenient and stable way.
11.2.1 Cookie
Cookie is a key value pair of information, sent by the server to the browser and then browser sends back this identifier to the server with every request there on.
There are two types of cookies:
Session cookies - are temporary cookies and are deleted as soon as user closes the browser. The next time user visits the same website, server will treat it as a new client as cookies are already deleted.
Persistent cookies - remains on hard drive until we delete them or they expire.
If cookie is associated with the client request, server will associate it with corresponding user session otherwise will create a new unique cookie and send back with response.
Simple code snippet to create a cookie with name sessionId with a unique value for each client:
Cookie cookie = new Cookie(“sessionID”, “some unique value”);
response.addCookie(cookie);
User can disable cookie support in a browser and in that case server will not be able to identify the user so this is the major disadvantage of this approach.
11.2.2 Hidden Field
Hidden fields are the input fields which are not displayed on the page but its value is sent to the servlet as other input fields. For example
<input type=”hidden” name=”sessionId” value=”unique value”/>
is a hidden form field which will not displayed to the user but its value will be send to the server and can be retrieved using request.getParameter(“sessionId”) in servlet.
As we cannot hardcode the value of hidden field created for session tracking purpose, which means we cannot use this approach for static pages like HTML. In short with this approach, HTML pages cannot participate in session tracking with this approach.
Another example will be any get requests like clicking of any link so above two are the major disadvantages of this approach.
11.2.3 URL Rewriting
URL Rewriting is the approach in which a session (unique) identifier gets appended with each request URL so server can identify the user session. For example if we apply URL rewriting on http://localhost:8080/HelloWorld/SourceServlet , it will become something like
http://localhost:8080/HelloWorld/SourceServlet?jSessionId=XYZ where jSessionId=XYZ is the attached session identifier and value XYZ will be used by server to identify the user session.
There are several advantages of URL rewriting over above discussed approaches like it is browser independent and even if user’s browser does not support cookie or in case user has disabled cookies, this approach will work.
Another advantage is , we need not to submit extra hidden parameter.
As other approaches, this approach also has some disadvantages like we need to regenerate every url to append session identifier and this need to keep track of this identifier until the conversation completes.
11.2.4 Session Tracking API
Servlets provide a convenient and stable session-tracking solution using the HttpSession API(remember we discussed about HttpSession Object in chapter 4 ?). This interface is built on the top of above discussed approaches.
Session tracking in servlet is very simple and it involves following steps
- Get the associated session object (HttpSession) using request.getSession().
- To get the specific value out of session object, call getAttribute(String) on the HttpSession object.
- To store any information in a session call setAttribute(key,object) on a session object.
- To remove the session data , call removeAttribute(key) to discard a object with a given key.
- To invalidate the session, call invalidate() on session object. This is used to logout the logged in user.
Let’s discuss Session Tracking API with the help of examples.
11.3 Examples
11.3.1 Write an example to print session Id , session creation time and last accessed time.
Solution- HttpSession API provides a method getId() which returns the associated session Id , getCreationTime() to get the session creation time and getLastAccessedTime() to get session last accessed time
getLastAccessedTime() and getCreationTime() returns the time as long data type so to convert it to display format, create a date object passing long value in it.
a. Add entry in web.xml
<servlet> <servlet-name>SessionInformationServlet</servlet-name> <servlet-class> com.servlet.tutorial.SessionInformationServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionInformationServlet</servlet-name> <url-pattern>/SessionInformationServlet</url-pattern> </servlet-mapping>
b. Write SessionInformationServlet which will get the session object and displays its attributes
package com.servlet.tutorial; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class SessionInformationServlet extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // get session object HttpSession session = request.getSession(); long creationTime = session.getCreationTime(); String sessionId = session.getId(); long lastAccessedTime = session.getLastAccessedTime(); Date createDate= new Date(creationTime); Date lastAccessedDate= new Date(lastAccessedTime); StringBuffer buffer = new StringBuffer(); buffer.append(" <HTML> <HEAD> </HEAD> <BODY>"); buffer.append("<STRONG> Session ID : </STRONG>" + sessionId); buffer.append(" <BR/> "); buffer.append("<STRONG> Session Creation Time </STRONG>: " + createDate); buffer.append(" <BR/> "); buffer.append("<STRONG> Last Accessed Time : </STRONG>" + lastAccessedDate); buffer.append(" <BR/> "); buffer.append(" </BODY> </HTML> "); PrintWriter writer = response.getWriter(); writer.print( buffer.toString() ); } }
Testing
Hit the URL http://localhost:8080/HelloWorld/SessionInformationServlet and it will display session related information (refer below figure).
Hold on for a couple of seconds and refresh the page .This time you will see that session Id and session creation time will remain same but the last accessed time will be changed (highlighted below)
Last accessed time is the time when you accessed the session last and since we did wait for some time and accessed the session again, it is modified.
Now close the browser and again hit the same URL (http://localhost:8080/HelloWorld/SessionInformationServlet) and see the difference. This time session Id is different which means new session is created because we closed the browser and opened a new one so server created a new session for the user.
11.3.2 Write an example to demonstrate storing and retrieving of an object from session.
Solution- To demonstrate this scenario, let’s create a servlet which will display the number of times this servlet has been invoked in a particular session. Also a user’s name will be passed as a query parameter.
a. Add entry in web.xml
<servlet> <servlet-name>SessionCounterServlet</servlet-name> <servlet-class>com.servlet.tutorial.SessionCounterServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionCounterServlet</servlet-name> <url-pattern>/SessionCounterServlet</url-pattern> </servlet-mapping>
b. Write a SessionCounterServlet. This servlet will store the request parameter (username ) in session and will increment the counter variable .
Servlet will verify if counter variable in session is available or not .If it is not available means new user has invoked the servlet and in this case store counter variable with value 1. Later on just increment the existing counter value by 1 and update it in session.
package com.servlet.tutorial; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class SessionCounterServlet extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // get session object HttpSession session = request.getSession(); String username = request.getParameter("username"); Integer counter = (Integer)session.getAttribute("counter"); if(counter==null) { counter=1; session.setAttribute("counter",counter); } else { session.setAttribute("counter",counter+1); } StringBuffer buffer = new StringBuffer(); buffer.append(" <HTML> <HEAD> </HEAD> <BODY>"); buffer.append("<STRONG> User name : </STRONG>" + username); buffer.append(" <BR/> "); buffer.append("<STRONG> Counter </STRONG>: " + counter); buffer.append(" <BR/> "); buffer.append(" </BODY> </HTML> "); PrintWriter writer = response.getWriter(); writer.print( buffer.toString() ); } }
Testing
Hit the url http://localhost:8080/HelloWorld/SessionCounterServlet?username=Dummy User
Every time we hit the url again , counter gets incremented
11.3.3 Explain session.invalidate() API with the help of example.
Solution- session.invalidate() invalidates the session or we can say it kills the corresponding server session. This API is most commonly used when a logged in user logs out. Once the session is invalidated, any other call on that server will throw an error.
- create a login.html to grab username and password of user.
- LoginServlet which will store the username in session and will create a link and clicking on that will invoke LogOut Servlet
- LogOutServlet will call session.invalidate() and will try to access session object fter invalidate which will throw an error.
Add Entry in web.xml
<servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.servlet.tutorial.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/LoginServlet</url-pattern> </servlet-mapping> <servlet> <servlet-name>LogoutServlet</servlet-name> <servlet-class>com.servlet.tutorial.LogoutServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LogoutServlet</servlet-name> <url-pattern>/LogoutServlet</url-pattern> </servlet-mapping>
Create login.html
<!DOCTYPE html> <html> <head> <title>Login Form</title> </head> <body> <form name="logonform" action="LoginServlet" method="POST"> Username: <input type="text" name="username"/> <br/> Password:<input type="password" name="password"/> <br/> <input type="submit" value="Submit"/> </form> </body> </html>
Create LoginServlet
package com.servlet.tutorial; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class LoginServlet extends HttpServlet { @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); String username=request.getParameter("username"); String password=request.getParameter("password"); HttpSession session = request.getSession(); session.setAttribute("username", username); PrintWriter writer = response.getWriter(); String message="Username is : "+ username + "<br/> Password is :" + password ; message = message + " <br/>To logout click on Logout Link <br/>" ; message = message + "<a href=\"LogoutServlet\"> Logout</a>"; writer.println(message); } }
Create LogoutServlet
package com.servlet.tutorial; 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; public class LogoutServlet extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); session.invalidate(); // try to access session object session.getAttribute("username"); } }
Testing
Hit the url http://localhost:8080/HelloWorld/lohin.html and enter any username and password
On submit it will invoke the LoginServlet
Clicking Logout link will invoke doGet() method of LogoutServlet which will invalidate the session and then tries to access the username from session.
By Default link click is a GET request so we implemented doGet() method of LogoutServlet and since it will kill the session, accessing it will throw exception (refer below figure)
11.4 Browser Session vs. Server Session
By default session tracking is based on cookie (session cookie) which is stored in browser memory and not on hard drive. So as soon as browser is closed, that cookie is gone and will not be retrieved again.
Corresponding to this session identifier, a server session is created at server and will be available until it is invalidated or maximum inactive time has been reached. When user closes the browser without logging off, server does not know that browser has been closed and thus server session remains active till configured maximum inactive time has been reached.
Maximum inactive session time ( in minutes) can be configured in web.xml like below
<session-config> <session-timeout>15</session-timeout> </session-config>
11.5 Store Attributes in Session object wisely.
At a first glance it looks very convenient to store attributes in session as it is available on any JSP or servlet within the same session. You have to be very careful while storing attributes in session as it can be modified by another JSP or servlet accidently which will result in undesirable behaviour.
Confused? Okay let’s think of a situation where your application has two servlets. Once servlets (FetchBalanceServlet) calls some database system and pulls out bank account balance and stores in a session variable (“accountBalance”) for later use.
You have another servlet “UpdateBalanceServlet” which updates the database with the value of “accountBalance” session variable.
There is another developer who is also working on your web application and does not know that you have created a session variable “accountBalance” so he also thought of creating a session variable with same name and stores it value as 0.
Now in any flow if prior the execution of UpdateBalanceServlet, if servlet written by another developer gets executed then it will change the session variable “accountBalance” value ot 0 and then UpdateBalanceServlet will update the account balance in database to 0