Other Built-In Objects
So far, you have been working with the request and response objects that are already available in the Servlet methods.
Along with these, there are a few other objects that you should be aware of, and in this lesson, you will be introduced to them.
HttpSession (a.k.a Session) Object
The HTTP protocol is a stateless protocol, and every request-response cycle initiated by the client to the backend server is independent of the next cycle; there is no state maintained between them. Once a browser makes a request to the backend, the HTTP protocol drops the connection to the server, and the conversation is over.
However, many times the interactions from the client to the server are part of multiple back-and-forth conversations consisting of many request-response cycles wherein the conversation is meaningful because the context from the previous conversations is kept. For e.g., when you log in to Amazon and start putting items into your shopping cart, there will be many request-response cycles going on between the client and the server; however, the server remembers the previous interactions, and hence the items that were kept in the shopping cart in a request-response cycle are still visible in the subsequent ones. This is because the server is maintaining a session on its side even though the HTTP protocol does not accommodate one.
In JEE applications, one of the ways of holding the state at the server side is using the session object. A session object can be retrieved from the request object, and you can add key-value pairs of information to it, much like a HashMap. When you want to retrieve the saved value, you can access it through the key.
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
String firstName = (String) session.getAttribute("fname");
String lastName = (String) session.getAttribute("lname");
String message = "Welcome to get method!";
if (firstName != null && lastName != null) {
message += " " + firstName + " " + lastName;
}
response.getWriter().append(message);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String firstName = request.getParameter("fname");
String lastName = request.getParameter("lname");
HttpSession session = request.getSession();
session.setAttribute("fname", firstName);
session.setAttribute("lname", lastName);
response.getWriter().append("Hello " + firstName + " " + lastName);
}
In the above example, the doPost method receives the first name and the last name of the user through request parameters. These values are then set in the session object.
When the user later invokes the doGet method, the values that are stored in the session are retrieved to display the welcome message.
But since HTTP is stateless, how does the server recognize the user? It is done through a session tracking technique using one of the below methods:
Using a cookie (called a
jsessionidcookie) to store a session ID in each browser that is saved on the client end. The browser passes the cookie to the server with each request, and using the session ID, the server retrieves the session object stored on the server. This cookie is deleted when the session ends.If cookies are disabled by the client, then the URL rewriting technique could be used to store the session ID in the URL itself as a query parameter, typically called 'jsessionid'.
If the cookies are disabled, another option is to use 'hidden' fields on the HTML form. The server can embed some hidden fields in the HTML form before forwarding the page to the client. These hidden fields will have a name/value stored when presented to the user. When the user submits the form, the values stored in the hidden fields are passed back to the server.
Note, however, that URL rewriting is not safe as the values are exposed, and anyone monitoring the network can gain access if the information passed on is sensitive. Session hijacking occurs if a jsessionid value is reused by anyone else on the network within the session timeout.
More on URL rewriting
URL rewriting is a technique where the base URL is appended with a query parameter that contains information pertinent to the server for when the client visits the same website again. When the server sends back a URL that the user can click, the URL has extra information. Here is an example:
www.example.com/another-page?jsessionId=1234
In the above example, the base URL www.example.com/another-page is appended with extra information from the server.
This URL is passed back to the client to click. When the user clicks this URL, the server gets to know who this person is through the jsessionid URL parameter that has
the session ID information, using which the server retrieves the required session.
Typical web servers make this appending of the URL to hold the session ID seamless if you use the below method:
response.encodeURL()
The above statement automatically adds the jsessionid URL param to the URLs that are part of the response.
Note:
- For every client's fresh interaction with the backend, a session object is created, whether that is used in the application or not.
- This session object is destroyed after the session timeout interval that is set on the server, which is typically 30 minutes. After the timeout, if the same client reconnects, a new session object is created.
- If the client opens multiple browser windows, it still uses the same session object on the server side.
- Holding values in sessions is out of vogue these days, as every time information is stored in the session, the server's memory is used. So if a million users are visiting the website, there will be a million session objects on the server, which dents the scalability of the server.
- Architecting a stateless server interaction is the norm in most scenarios.
This technique of keeping the key-value pair inside an object for future use is the same technique that is used to hold
information in the request object when you set an attribute
to the request and forward it to another entity to handle the request.
However, the attributes that are set in the request object are dropped as soon as it reaches its destination,
and hence sending attributes from one
endpoint to another through the request object is preferred over using a session object.
ServletContext (a.k.a Application) Object
Along with the session, you also have access to the ServletContext, popularly known as the application object, where you can keep key-value pairs for the entire application and not just for the specific session.
Here too, you set the key-value pair using the attribute as shown below:
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("appName", "MyFirstWebApp");
Here too, using getAttribute gets you the value as an Object which can be cast to the specific object that you set.
Values set in the application object are available across all servlets and JSP pages.
Remember, however, that the application object should only keep values that are meant for the entire application and not those of individual users of the application.
[!CALLOUT]Important points to remember
- Keeping state using sessions is not preferred these days.
- In a JSP page, the application object is available as the implicit object 'application'.
- In a JSP page, the session object is available as the implicit object 'session'.
- Typically, when a user logs in, a session object is initialized, and when the user logs out of the system, the session is emptied in the code.
Cookies
A cookie is a small object created by the server that can hold key-value pairs, just like the other objects we have discussed. This cookie can be sent back to the client's browser over HTTP so that it can be stored on the client's computer.
The next time the same client makes a request to the backend, the cookie is sent to the server on HTTP. The value that is stored in the cookie can be retrieved by the server to take appropriate action for the user.
Typically, the server stores some valuable information about the specific client in the cookies.
The life of the cookie can be set by the server, and its maximum lifespan is 3 years. But users can disable cookies on their browsers, in which case the application server cannot make use of cookies for sending and receiving information about the user.
Cookies are tied to the domain or subdomain names of the application server, and most browsers limit the cookie size to 4KB and can accept only 20 cookies for each domain/subdomain.
Typical scenarios where cookies are used:
- to hold the session for the user
- to save a user's browsing history, which the backend server can use to show relevant ads
- to save form details like username, address, etc., that is used to autofill the form the next time.
- to customize pages that display information like news, weather, stock ticker quotes, etc.
Cookies are created and set on the response object and are received back through the request object. Here is an example:
Cookie cookie = new Cookie("mbccUserId", "1234");
response.addCookie(cookie);
The above code creates a cookie and sets a name/value (name=mbccUserId and value=1234) pair that the backend can use the next time the same
client visits the website. The server can retrieve the cookie in the next visit as shown below:
Cookie[] cookies = request.getCookies();
String userId = null;
for(Cookie cookie : cookies){
if("mbccUserId".equals(cookie.getName())){
userId = cookie.getValue();
}
}