Tuesday, March 29, 2011

Chapter 28: The setStatus Method

In the previous chapter, we saw the sendError method. We saw how Tomcat implements it and we saw a wrapper method that used it but did some handling for custom error messages. Well, in this chapter, we are going to see the twin brother of the sendError method, the setStatus method.

So, lets get started…

The setStatus Method

The setStatus method sets the status code for a given response. Use this method, instead of sendError, when there is no exception or serious error (such as a blocked or a page inaccessible to the user). If there is a serious error, the sendError method should be used; otherwise use setStatus. Like the sendError method, using this method clears the buffer, but leaves cookies and other headers unmodified.

Let us now take a look at how Tomcat has implemented the setStatus method.

Code:

/**
* Set the HTTP status and message to be returned
* with this response.
*
* @param status The new HTTP status
* @param message The associated text message
*
* @deprecated As of Version 2.1 of the Java Servlet
* API, this method has been deprecated due to the
* ambiguous meaning of the message
* parameter.
*/
public void setStatus(int status, String message) {

if (included)
return; //Ignore any call from included servlet

this.status = status;
this.message = message;

}

As you can see in the code above, this method has been deprecated because the message functionality isn't reliable. The setStatus method will remain (the one taking only a status code), but without a message parameter in a future version, Maybe.

However, you can always write a wrapper to use the setStatus method effectively. (Just like we did for the sendError method)

Code:

/**
* statusManager Method.
*/
void checkCarStatus(HttpServletResponse response)
throws ServletException
{
if( !isValid(carName) )
{
response.setStatus(response.SC_BAD_REQUEST);
} else if( !isValid(carModel) )
{
response.setStatus(response.SC_BAD_REQUEST);
} else if( !isValid(carMakeYear) )
{
response.setStatus(response.SC_BAD_REQUEST);
} else if( !isValid(creditCardNumber) )
{
response.setStatus(response.SC_BAD_REQUEST);
} else
{
response.setStatus(response.SC_OK);
}
}

The code above is pretty straight forward. I suppose this can be used in a car repair garage. We first check if the cars name is valid and then check if the cars model is valid and then check its manufacture year. We also check the credit card number of the customer (because we need to get paid right) and if all these are valid, we set a OK response, else we set a bad request response. It's a simple implementation and you can alter it anyway you want, as long as it serves your purpose and uses the setStatus method, we are good…

The same status codes that are used for the sendError method can be used for the setStatus method, too. The primary difference is that the former prevents any further response to the client and throws an exception if you try. This is not so for the latter. There is one point of confusion with the setStatus method. The specification says the buffer is cleared when called. In other words, you should set this first before you send anything back to the client. However, I looked in Tomcat and did not observe the buffer being cleared. The following snippet:

out.println("pre setStatus message.");
response.setStatus(HttpServletResponse.SC_OK);
out.println("post setStatus message.");

produced this:
pre setStatus message.
post setStatus message.

Exam Trivia:
Containers don't always follow the specifications! As you can see, Tomcat does not clear the buffer as the specification says. The specification doesn't make sense as of this moment because, the way Tomcat implemented it is better. However, since other containers may follow the specification here and the exam will be based on the specification, assume that is how it actually works.

Previous Chapter: Chapter 27 - sendError Method

Next Chapter: Chapter 29 - WebApp Log

Chapter 27: The sendError Method

In the chapter on introduction to Servlet Exception Handling, we have used the term, use the sendError method and in the previous chapter, we saw an example that actually used this method. This chapter is dedicated solely for the purpose of explaining the features of this method and how to use it effectively.

So, lets get started!!!

The sendError Method

The sendError method sends an error response to the client using the specified status (Remember the bunch of status codes we saw in one of the previous chapters?). Using this method clears the buffer. The server creates an HTML-formatted server error page. This page contains a default, or the message you provide, as an argument. It also sets the content type to “text/html”, even if you changed this, but leaves cookies and other headers unmodified.

Exam Trivia:
We cannot or rather should not send data to a client after the sendError() method is invoked. Once this method is invoked, all the buffered output will be discarded. If data has been written to the response buffer but not yet returned to the client (i.e., response not committed), the data is cleared and replaced with the data sent by the sendError() method. Data written to the response after the sendError() is called is ignored. However, if you write data to the response buffer and try to commit it after the sendError is invoked, an IllegalStateException will be thrown.
Be cautious and watch out for code that does exactly this in the exam question. It may look legit but it will throw an exception and you may overlook the exception choice in the answer.

The sendError method will set the appropriate headers and content body for an error message to return to the client. An optional String argument can be provided to the sendError method, which can be used in the content body of the error. Using this method will commit the response (if not already committed) and terminate it. The data stacked in the output stream to the client before calling sendError() method is ignored.

Internally, the servlet base classes prevent you from writing to the output stream after calling sendError(). In the write-to-stream methods there is a test for a previous error in the servlet that looks like this:

//suspended is a flag set once output is committed
if (suspended)//true if sendError has been called
throw new IOException
(sm.getString("responseBase.write.suspended"));

That is why you can't add to the outputstream after calling sendError().
The best way to understand the sendError() method is to look at it directly. Lets take a look at some sample code that will help us do just that.

Code: This is the actual code implementation of how Tomcat implements the sendError method.

/**
* Send an error response with the status and message.
*
* @param status HTTP status code to send
* @param message Corresponding message to send
*
* @exception IllegalStateException if this response has
* already been committed
* @exception IOException if an input/output error occurs
*/
public void sendError(int status, String message)
throws IOException
{
if (isCommitted())
throw new IllegalStateException
(sm.getString("httpResponseBase.sendError.ise"));

if (included)
return; //Ignore any call from an included servlet

setError();

// Record the status code and message.
this.status = status;
this.message = message;

// Clear any data content that has been buffered
resetBuffer();

// Cause the response to be finished
// (from the application perspective)
setSuspended(true);
}

If you observe the code above, the first thing it does is, throw an IllegalStateException if the response was already committed. Then it returns from the method if it is not invoked by the outermost servlet. The next thing it does is, call the setError method which updates an internal flag. Then it updates the status and message fields. These two fields are of most importance to us. Then it clears the buffer and finally suspends any further output stream access.

You can make better use of this method if you create a wrapper for it. You might want to do this if you care to send custom messages to the client rather than accept the default ones provided by the container.

Below is code for a sample wrapper that can be used for sending custom messages instead of using the default one.

Code:

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.PrintWriter;
import java.io.IOException;

public class ErrorHandlingServlet extends HttpServlet
{
//your own custom flag:
static final int SC_CUSTOM_ERROR_FIRST_NAME = 3229;

public void sendError(HttpServletResponse response,
int code)
throws ServletException, IOException
{
// Message sent by sendError().
String message = getErrorMessage(code);

if(message.equals("NONE"))
{
response.sendError(HttpServletResponse.SC_ FORBIDDEN);
} else
{
response.sendError(HttpServletResponse.SC_ FORBIDDEN,
message);
}

//update your own log
//logError(code, message);
}

public String getErrorMessage(int code)
{
String message = "NONE";
switch (code)
{
case HttpServletResponse.SC_OK:
return ("OK");
case HttpServletResponse.SC_ACCEPTED:
return ("Accepted");
case HttpServletResponse.SC_BAD_GATEWAY:
return ("Bad Gateway");
case HttpServletResponse.SC_BAD_REQUEST:
return ("Bad Request");
case HttpServletResponse.SC_CONFLICT:
return ("Conflict");

//There are a lot more codes.
//Just put a few for example

//first custom message; overrides the default message
case HttpServletResponse.SC_GONE:
return ("Sorry, this resource +
"is not available any more.");
case
HttpServletResponse.SC_HTTP_VERSION_NOT_ SUPPORTED:
return ("Hey! You are doing something Hinky" +
" and we do not support it.");
case HttpServletResponse.SC_INTERNAL_SERVER_ERROR:
return ("I Have no clue as to what happened, but it "
"was a bad server error");
case HttpServletResponse.SC_MOVED_PERMANENTLY:
return ("This Page has moved For good"
"permanently!");
// You can add a lot more custom error messages and provide
// handling for it.
default:
return ("NONE");
}
}
}


Previous Chapter: Chapter 26 - Returning an Error Code to the Client

Next Chapter: Chapter 27 - setStatus Method

Monday, March 28, 2011

Chapter 26: Returning an Error Code to the Client

In the previous chapter, we learnt what the error codes are and what they signify. We also saw an introduction to servlet exception handling. Before we get any further on this topic of exception handling, we need to know how to send error codes to the browser. That is exactly what we are going to learn now.

So, lets get started!!!

Returning an Error Code to the Client

The servlet is just as prone to logic errors and bugs as standalone applications. Java has a smart facility for handling them in both environments. Let's look at a very simple example of how you might handle an error in a servlet. The TestErrorServlet servlet illustrates the use of the sendError() method. It takes an error code as a parameter and an optional custom message associated with that error

Source Code:

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletException;
import java.io.PrintWriter;
import java.io.IOException;

public class TestErrorServlet extends HttpServlet {

public void service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

response.sendError(HttpServletResponse.SC_FORBIDDEN,
"Sorry, restricted to Authorized Personnel.");
}
}

Compile the TestErrorServlet file and hit the servlet with your browser.
The container will send an error message to the client. You should see a page that looks like below.


Previous Chapter: Chapter 25 - Introduction to Servlet Exception Handling

Next Chapter: Chapter 27 - sendError Method

Chapter 25: Introduction to Servlet Exception Handling

Any technology, any programming language you learn, exception handling is an integral part of it. And the SCWCD exam covers topics related to Exception Handling in the Servlet Technology as well. Though, there are numerous ways of customized error handling available with servlets, the exam covers two main topics. Using the SENDERROR and SETSTATUS.

That is exactly what we are going to learn in this chapter and the next few chapters too.

So, lets get started!!!

Introduction to Servlet Exception Handling:

The way in which you create and manage exceptions in servlets is slightly different from how you do this with standalone applications.

We always use the response object (HttpServletResponse) and not the request object, to tell the browser that there is a problem.

The exam includes both exceptions (The ones caused by the Servlet) and HTTP Error Codes (Those you send back to the client).

Before we jump into the world of exceptions, lets quickly review the HTTP Protocol standards. This is essential because, the servlets communicate with clients using HTTP and it is helpful to know a little about this protocol.

The HTTP Protocol:

The HTTP protocol is a request/response scheme where a client sends a request to the server. There are four major portions of this request, which include, a request method (GET, POST…), URI (such as www.abc.com), protocol version (HTTP/1.1), and finally a MIME-like message. This message can be any size, and normally includes request modifiers, client information, and body content.

In this series of chapters, we will learn how we can send error information to the client using the sendError method, which sends a status line with the protocol version and a success or error code. It also returns a MIME like message containing server information, entity meta information and body content. You must remember that both the severity and type of error to properly tell the client what went wrong. Your error handling logic needs to determine the most appropriate severity for a particular error.

After receiving a request, the server responds. It returns an HTTP response message. The first line of this response message is called the status line. The status line has three parts. They are, in this order, protocol version, numeric status code, and status textual phrase. This status code is what you are setting when you use sendError and setStatus methods.

The Error Codes:

If you have been using the internet and J2EE applications for a while, you are sure to have encountered the 404: PAGE NOT FOUND message at some websites. This tells you that the URL is bad. i.e., if you try login to www.thisissurelyanincorrectwebsite.com you will probably get this message. The emphasis is on the number 404, this is the status code, a 3 digit integer number. The first digit defines the class of response, while the last two digits do not have any categories; they give an indication of what the problem is.

Let us now take a look at all the error codes that we can encounter in a HTTP based J2EE system. This list just contains the broad categorization based on the 1st digit.

Number Type Description
1XX Informational Request received, continuing to process.
2XX Success The action was successfully received, understood, and accepted.
3XX Redirection Further action must be taken in order to complete the request.
4XX Client Error The request contains bad syntax or cannot be fulfilled.
5XX Server Error The server failed to fulfill an apparently valid request.
While, the above table describes five set of status codes, we will primarily focus on the Server Error Category – the 5XX codes.

As mentioned previously, the HTTP protocol is a request/response scheme where a client sends a request to the server. When you need to inform the client of a problem at the server end, you call the sendError method. This causes the server to respond with a status line, with protocol version and a success or error code (this is what sendError affects directly). Of course, it also returns a MIME-like message containing server information, entity meta information, and body content.

Actually, the sendError() and setStatus are closely related. In fact, they both set the error message to be displayed by the client and the status code used by the client. The default status code is HttpServletResponse.SC_OK ="OK"; however, there are a few other standard codes as well.
That being said, lets take a look at the list of status codes available. These codes were defined by the W3C and are sanctioned by the Internet Society (ISOC). The constant names, quoted messages that get displayed in the browser, and code descriptions are a combination of the servlet specification and Tomcat's implementation of that specification. The exam will not test your memory of these directly. However, taking five minutes to study this table will help you understand what these codes do and figure out which ones you need to use with the sendError and setStatus methods. Notice that the RFC column provides the Request For Comment document and section, the Internet's way of documenting standards. Also, some browsers allow the user to hide “friendly” error messages. If they do that, they will not see many of these errors, even if they occur.

Code Constant RFC Message Description
100 SC_CONTINUE 10.1.1 “Continue” Client can continue.
101 SC_SWITCHING_PROTOCOLS 10.1.2 “Switching Protocols” Server is switching protocols according to Upgrade header.
200 SC_OK 10.2.1 “OK” Request succeeded normally.
201 SC_CREATED 10.2.2 “Created” Request succeeded and created a new resource on the server.
202 SC_ACCEPTED 10.2.3 “Accepted” Request was accepted for processing but was not completed.
203 SC_NON_AUTHORITATIVE_INFORMATION 10.2.4 “Non-Authoritative Information” Meta information presented by the client did not originate from the server.
204 SC_NO_CONTENT 10.2.5 “No Content” Request succeeded but there was no new information to return.
205 SC_RESET_CONTENT 10.2.6 “Reset Content” Agent should reset the document view which caused the request to be sent.
206 SC_PARTIAL_CONTENT 10.2.7 “Partial Content” Server has fulfilled the partial GET request for the resource.
300 SC_MULTIPLE_CHOICES 10.3.1 “Multiple Choices” Requested resource corresponds to any one of a set of representations with each with its own specific location.
301 SC_MOVED_PERMANENTLY 10.3.2 “Moved Permanently” Resource has permanently moved to a new location and future references should use a new URI with their requests.
302 SC_MOVED_TEMPORARILY 10.3.3 “Moved Temporarily” Resource has temporarily moved to another location but future references should still use the original URI to access the resource.
303 SC_SEE_OTHER 10.3.4 “See Other” Response to the request can be found under a different URI.
304 SC_NOT_MODIFIED 10.3.5 “Not Modified” Conditional GET operation found that the resource was available and not modified.
305 SC_USE_PROXY 10.3.6 “Use Proxy” Requested resource must be accessed through the proxy given by the Location field.
307 SC_TEMPORARY_REDIRECT 10.3.8 N/A Requested resource resides temporarily under a different URI. The temporary URI should be given by the Location field in the response.
400 SC_BAD_REQUEST 10.4.1 “Bad Request” Request sent by the client was syntactically incorrect.
401 SC_UNAUTHORIZED 10.4.2 “Unauthorized” Request requires HTTP authentication.
402 SC_PAYMENT_REQUIRED 10.4.3 “Payment Required” Reserved for future use.
403 SC_FORBIDDEN 10.4.4 “Forbidden” Server understood the request but refused to fulfill it.
404 SC_NOT_FOUND 10.4.5 “Not Found” Requested resource is not available.
405 SC_METHOD_NOT_ALLOWED 10.4.6 “Method Not Allowed” Method specified in the Request-Line is not allowed for the resource identified by the Request-URI.
406 SC_NOT_ACCEPTABLE 10.4.7 “Not Acceptable” Resource identified by the request is only capable of generating response entities that have content characteristics not acceptable according to the accept headers sent in the request.
407 SC_PROXY_AUTHENTICATION_REQUIRED 10.4.8 “Proxy Authentication Required” Client must first authenticate itself with the proxy.
408 SC_REQUEST_TIMEOUT 10.4.9 “Request Timeout” Client did not produce a request within the time that the server was prepared to wait.
409 SC_CONFLICT 10.4.10 “Conflict” Request could not be completed due to a conflict with the current state of the resource.
410 SC_GONE 10.4.11 “Gone” Resource is no longer available at the server and no forwarding address is known. This condition should be considered permanent.
411 SC_LENGTH_REQUIRED 10.4.12 “Length Required” Request cannot be handled without a defined Content-Length.
412 SC_PRECONDITION_FAILED 10.4.13 “Precondition Failed” A precondition given in one or more of the request-header fields evaluated to false when it was tested on the server.
413 SC_REQUEST_ENTITY_TOO_LARGE 10.4.14 “Request Entity Too Large” Server is refusing to process the request because the request entity is larger than the server is willing or able to process.
414 SC_REQUEST_URI_TOO_LONG 10.4.15 “Request URI Too Long” Server is refusing to service the request because the Request-URI is longer than the server is willing to interpret.
415 SC_UNSUPPORTED_MEDIA_TYPE 10.4.16 “Unsupported Media Type” Server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.
416 SC_REQUESTED_RANGE_NOT_SATISFIABLE 10.4.17 “Requested Range Not Satisfiable” Server cannot serve the requested byte range.
417 SC_EXPECTATION_FAILED 10.4.18 “Expectation Failed” Server could not meet the expectation given in the Expect request header.
500 SC_INTERNAL_SERVER_ERROR 10.5.1 “Internal Server Error” Error inside the server which prevented it from fulfilling the request. This error represents many server problems such as exceptions or perhaps a database hiccup.
501 SC_NOT_IMPLEMENTED 10.5.2 “Not Implemented” Server does not support the functionality needed to fulfill the request.
502 SC_BAD_GATEWAY 10.5.3 “Bad Gateway” Server received an invalid response from a server it consulted when acting as a proxy or gateway.
503 SC_SERVICE_UNAVAILABLE 10.5.4 “Service Unavailable” Server is temporarily overloaded and unable to handle the request.
504 SC_GATEWAY_TIMEOUT 10.5.5 “Gateway Timeout” Server did not receive a timely response from the upstream server while acting as a gateway or proxy.
505 SC_HTTP_VERSION_NOT_SUPPORTED 10.5.6 “HTTP Version Not Supported” Server does not support or refuses to support the HTTP protocol version that was used in the request message.
Let me repeat, you need not memorize these status codes but knowing them would be useful to understand the servlet exception handling concepts.

Previous Chapter: Self Test - Chapters 20 to 24

Next Chapter: Chapter 26 - Returning Error Codes

Thursday, March 24, 2011

Self Test: Chapters 20 to 24

Questions

Question 1:
Which of the following two methods are used to track or store the session ID?
A. encodeURL()
B. sessionTrack()
C. sessionUpdate()
D. encodeRedirectURL()

Question 2:
How do you create a session?
A. createSession()
B. makeSession()
C. callSession()
D. getSession()

Question 3:
How do you retrieve a session object across multiple requests to the same or different servlets within the same WebApp?
A. retrieveSession()
B. findSession()
C. getSession()
D. callSession()

Question 4:
How do you store objects into a session object?
A. put(String, Object)
B. setAttribute(String, Object)
C. addObject(Object)
D. putObject(String, Object)

Question 5:
How do you know if a session is alive?
A. Look in the cookies.
B. getSession(false)
C. isSessionAlive()
D. Exception thrown if you try to create one when one already exists.

Question 6:
How do you destroy or expunge a session?
A. Session.isAlive = false;
B. Session.isNew(false)
C. invalidate()
D. removeSession()

Question 7:
How do you know when a particular object is added to a session?
A. getCreationTime()
B. getAttribute(Date)
C. Session.attributeDate(index)
D. attributeAdded(HttpSessionBindingEvent)

Question 8:
How do you know when a session is created?
A. sessionDidActivate(HttpSessionEvent)
B. You check with sessionIsAlive().
C. You only know when it is killed.
D. When the SESSIONID becomes null.


Question 9:
How do you know when a session is destroyed?
A. sessionBound(HttpSessionEvent)
B. sessionFinalize(HttpSessionEvent)
C. sessionWillPassivate(HttpSessionEvent)
D. valueBound(HttpSessionEvent)

Question 10:
Given that URL-rewriting must be used for session management, identify the query string attribute used when URL-rewriting.
A. sessionid
B. servletid
C. jsessionid
D. containerid

Question 11:
Where are cookies stored?
A. On the server.
B. In web.xml.
C. On the client.
D. In HTML.


Question 12:
Where are session IDs stored?
A. In cookies.
B. In HTML form fields.
C. In query strings.
D. Session IDs are not stored.

Question 13:
Which two technique can be used by a Web container to manage session IDs?
A. deleteAttribute(String)
B. attributeRemove(String)
C. removeAttribute(String)
D. setAttribute(null)

Question 14:
How do you get the date stamp of the session's creation?
A. getCreationTime()
B. sessionDate()
C. getSession(Date)
D. From the response object.

Answers:

Answer 1: A and D. You append the session ID in URLs by calling the response's encodeURL(URL) (or encodeRedirectURL()) method on all URLs returned by a servlet. This method includes the session ID in the URL only if cookies are disabled; otherwise, it returns the URL unchanged.

Answer 2: D. To get the current session in a servlet, you call the getSession() method of HttpServletRequest. You have one parameter to think about. If you don't provide a boolean, this method will create a session if one doesn't exist. The same behavior occurs when you provide a true boolean. However, the container will not create a new session if it doesn't already exist when you use a false argument.

Answer 3: C. This is the same question as #2, but stated differently. You call the getSession() method of HttpServletRequest to create a session.

Answer 4: B. You use the setAttribute(java.lang.String name, java.lang.Object value) method to add objects to a session. The other methods listed are incorrect.

Answer 5: B. This is somewhat difficult. You use getSession(false) method and test for a null result.
HttpSession session = request.getSession(false);
if (session = null) {
//do something about lacking a session
}

If you get a null then the session is alive. You can also check for the session ID with getId(), which returns the id of the session as a String representing the unique identifier assigned to this session. If the session is dead, it will return a null.

Answer 6: C. Only the invalidate() method can destroy a session. Notice that the session can't be referenced after this method has been called. A and D are incorrect and B isn't used properly.

Answer 7: D. The attributeAdded(HttpSessionBindingEvent se) method gets called as the notification that an attribute has been added to a session. The other options are incorrect.

Answer 8: A. The sessionDidActivate(HttpSessionEvent) method is called when the session has just been activated. The other options are incorrect.

Answer 9: C. The sessionWillPassivate(HttpSessionEvent) method is called as the notification that the session is about to be passivated. This is strange language so don't feel bad. They should have used another term such as alive or destroy. A and B are incorrect. D (valueBound(HttpSessionBindingEvent)) is the notification to the object that it is being bound to a session, but doesn't tell you about the session being destroyed.

Answer 10: C. The jsessionid is the parameter that is appended to URLs by the encodeURL() method when cookies are not available to maintain state. The other options are incorrect.

Answer 11: C. Cookies are stored on the client only.

Answer 12: A and C. Session IDs are stored in cookies on the client machine. If cookies are turned off, session IDs can be stored in query strings.

Answer 13: C. The removeAttribute(java.lang.String name) method removes an attribute. It deletes it from the session object. The other options are incorrect.

Answer 14: A. The getCreationTime() method returns a long containing the date stamp of creation. The other options are incorrect.

Previous Chapter: Quick Recap - Chapters 20 to 24

Next Chapter: Chapter 25 - Introduction to Servlet Exception Handling

Quick Recap: Chapters 20 to 24

Let us now quickly review what we learnt about Sessions in the previous chapters.

Session Introduction:

• We need Sessions to maintain or persist user information during a sequence of events on a website by a user
• Session persistence is usually implemented using Cookies but it can be implemented using URL Rewriting, or hidden form fields
• The getAttribute and setAttribute methods of the HttpSession are used to set and retrieve values from the Session
• You can get a session by using the getSession method of the Request class.
HttpSession session = request.getSession(true);

Session Event Listeners:

• The common event listeners we will encounter are: HttpSessionActivationListener, HttpSessionAttributeListener and HttpSessionBindingListener
• Each has methods that can help us capture and process actions like when a session is created/destroyed, when a value is added/removed from the session etc.

Session Invalidation:

• Invalidating a session after a certain time period is a common occurrence
• Usually websites that display sensitive information have a time-out of around 10 mins
• The session would automatically expire after the time-out is reached (If the session is inactive)

Key Terms we learnt in these chapters:

• Session
• Session ID
• Session Timeout
• Session Attribute
• Session Events
• Listeners

Previous Chapter: Chapter 24 - Session Tracking through URL Rewriting

Next Chapter: Self Test - Chapters 20 to 24

Chapter 24: Session Tracking Through a URL Rather Than a Cookie

Session Tracking is very useful as you might have learnt in the past few chapters. There is also a feature wherein you can use URL Rewriting instead of using cookies (all our examples in the past chapters were using cookies so this one is new). In this chapter, you are going to learn just that.

So, lets get started!!!

URL Rewriting:

A Web container associates a session with a user by sending and receiving an identifier. This session ID is passed between the client and server. You could place this identifier in the HTML, but servlets are already designed to track this identifier if it is placed in a cookie or in the query string. The cookie is the easiest and happens automatically for you when you create a session. If the user turns off cookies then you can send the identifier back and forth in the query string by including it in every URL that is returned to the client. Though this is a bit of a painful task and is not necessarily used always, it is advised to learn it to cope with situations where cookie tracking is turned off frequently by your users and you still need to use sessions.

You append the session ID in URLs by calling the response's encodeURL(URL) or the encodeRedirectURL() method on all URLs returned by a servlet. This method includes the session ID in the URL only if cookies are disabled; otherwise, it returns the URL unchanged.

Exam Trivia:

The encodeURL method will use URL rewriting only if cookies are disabled else it will not modify the URL and the session will continue to use cookies. Remember that for the exam. Unless the question explicitly states that the cookies are turned off, don't assume it is and think that the URL will be modified by this method


Example Code using URL Rewriting:

Now that we know how to append a session ID in the URL, lets look at an example that does that for us.

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class TestURLRewriteServlet extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
HttpSession session = request.getSession(true);
session.setAttribute("sessionNumber", new Integer(22));

response.setContentType("text/html");

PrintWriter out = response.getWriter();
out.println("< html >");
out.println("< body bgcolor=\"white\" > ");
out.println("< head >");

String title = "Session ID Is In URL";
out.println("< title >" + title + "< / title >");
out.println("< / head >");
out.println("< body >");
out.println("< center >");

out.println("< h1 >" + title + "< / h1 >");


out.println("< P >");
out.print(response.encodeURL("ExampleURL"));
out.println("< P >");
out.print(response.encodeURL("ExampleURL?name=" + "Car&value=Ferrari"));

out.println("< / center >");
out.println("< / body >");
out.println(" < / html >");

out.println("< / body >");
out.println("< / html >");
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
When I first ran this code, my cookies were turned on. I saw this in my browser:
ExampleURL?name=Car&value=Ferrari

However, I then turned off cookies and received this on the next visit:
ExampleURL;jsessionid=62A027E37975F305B07555859780E423?name=Car&value=Ferrari

The JSESSIONID attributed displayed in the output above is used to track sessions when cookies are turned off. This JSESSIONID attribute would get appended to the query strings (URL) when we use the encodeURL() or encodeRedirectURL() methods.

You will probably see this attribute mentioned on the exam. So, just remember whatever you learnt in this chapter…

Previous Chapter: Chapter 23 - Invalidating Sessions

Next Chapter: Quick Recap - Chapters 20 to 24

Chapter 23: Invalidating Sessions

Invalidating sessions is very important because, the session is going to contain some data, data that you might not want someone else to use. For example, lets say you login to your banks website on your office computer and receive an urgent call from your wife. In a hurry you leave your desk unattended and also without logging off the banks website. Now, lets say after an hour someone else from your office walks by your desk and sees that you are logged on to your banks website and are nowhere to be seen. They can use the website to transfer funds to their account. Wouldn't that be an issue? Yes, it would be. That is exactly why all secure websites have a session timeout feature wherein, the users session will be terminated automatically if it senses that the session has been idle for a few mins (Usually 5 mins or 10). This way, you are safe.
So, after all this story, I guess you know where I am coming to. We are going to learn how to invalidate a session in this chapter.

So, lets get started!!!

Invalidating Sessions

Invalidating sessions is important as well as tricky. You need to be cautious when you encounter questions in the exam that asks whether the session would be invalidated under a particular scenario. They might lure you into thinking that the session might be invalidated where in reality the session would be very much active.

Exam Trivia
When is session invalid Surfing to another Web site does not invalidate a session, but quitting the browser does. The user can surf from your page to somewhere else and back again without losing the session. The session will remain intact unless the user was away longer than the timeout.

The six most commonly used methods to invalidate a session are

• Calling HttpSession.setMaxInactiveInterval(int secs) method, explicitly setting how many minutes the session will last.
• The session will automatically be invalid after a certain time of inactivity (Tomcat default is 30 minutes). You need to remember that this 30 minutes is not a hard and fast rule for all servers. It might vary from one server to another and is configurable. So you can have it configured to last 25 mins in your server and I can have it to last 20 mins.
• The user closes all browser windows. Note that, here the session will timeout rather than directly triggering a session invalidation.
• The session will expire when it is explicitly invalidated by a servlet by calling invalidate().
• The server is stopped or crashes. Note that this event might not trigger a session invalidation. A Web container that permits failover might persist the session and allow a backup Web container to take over when the original server fails.
• You can set the default timeout in the web.xml file ().

Don't worry about the web.xml file just yet. We shall be covering it in great detail in future so for now just remember that you can set the session timeout interval in the web.xml file and that is as much you need to know at this point of time.

Previous Chapter: Chapter 22 - Session Event Listeners

Next Chapter: Chapter 24 - Session Tracking Through URL Rewriting

Chapter 22: Session Event Listeners

In one of the previous chapters, Interfaces & Listeners in the web context we saw about interfaces and event listeners. In this chapter we are going to take a look at the Event Listener that is linked to the HttpSession.

So, lets get started!!!

Session Event Listeners

The listeners that can be used to capture session event actions are:
1. HttpSessionActivationListener
2. HttpSessionAttributeListener
3. HttpSessionBindingListener

Lets look at them one by one in detail.

HttpSessionActivationListener

The purpose of this listener is to look for events such as when a session will be activated or passivated. The listener in turn extends the java.util.EventListener. The methods in it are:

• sessionDidActivate(HttpSessionEvent se) - This is the notification that the session has just been activated.
• sessionWillPassivate(HttpSessionEvent se)- This is the notification that the session is about to be passivated.

Exam Trivia:
Session Moving Between JVMs The specification dictates that a container that migrates a session between VMs or persists sessions is required to notify all attributes bound to sessions implementing HttpSessionActivationListener.

HttpSessionAttributeListener:

The HttpSessionAttributeListener interface enables an object to monitor changes to the attribute lists of sessions within a given Web application. The HttpSessionAttributeListener in turn extends java.util.EventListener. The methods in it are

• attributeAdded(HttpSessionBindingEvent se)- This is the notification that an attribute has been added to a session.
• attributeRemoved(HttpSessionBindingEvent se)- This is the notification that an attribute has been removed from a session.
• attributeReplaced(HttpSessionBindingEvent se)- This is the notification that an attribute has been replaced in a session.

We can use these methods when monitoring the attributes of a particular session.

HttpSessionBindingListener

The last listener we are going to look at is the HttpSessionBindingListener. The HttpSessionBindingListener is used to track the events surrounding the binding and unbinding of a session. This event listener causes an object to be notified when it is bound to or unbound from a session. The interface is HttpSessionBindingListener in turn extends java.util.EventListener.

This will be triggered when a servlet is coded to explicitly unbind an attribute from a session, due to a session being invalidated or a session timeout. The methods in it are

• valueBound(HttpSessionBindingEvent event)- This is the notification to the object that it is being bound to a session and identifies the session.
• valueUnbound(HttpSessionBindingEvent event)- This is the notification to the object that it is being unbound from a session and identifies the session.

You might want to know when an object is added or removed from a session to handle, say, a shopping cart checkout. And this listener is just designed to help you with that.

Code Examples to Understand the Listener Usage:

Now that we know what these listeners are, lets look at a sample code that is going to handle these events. As you already know, if a class has to handle certain events, someone has to generate them, right? So here, the first code example is going to generate our events and the second guy is going to handle them.

Code 1:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class TestSessionEventsServlet extends HttpServlet {

public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{

// Activities that trigger listener events
HttpSession session = request.getSession(true);
session.setAttribute("attributeName", "firstValue");
session.setAttribute("attributeName", "firstValue");
session.removeAttribute("attributeName");
session.invalidate();
}
}

The above code does nothing but, create a session and then set/remove attributes and then invalidate the session.

Code 2:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SessionActivityListener
implements HttpSessionListener,
HttpSessionAttributeListener
{
public void attributeAdded(HttpSessionBindingEvent event)
{
//do something when attribute is added
}

public void attributeRemoved(HttpSessionBindingEvent
event) {
{
//do something when attribute is removed
}

public void attributeReplaced(HttpSessionBindingEvent
event) {
{
//do something when an attribute is replaced
}

public void sessionCreated(HttpSessionEvent event) {
{
//do something when session is created
}

public void sessionDestroyed(HttpSessionEvent event) {
{
//do something when session is destroyed
}
}

The first servlet created the events we wished to capture and this above class will handle them. Actually I havent put any event handling code in any of the methods. They are all blank. But, in realtime, you would want to have code inside each of the event handling methods that would let you do something. For ex: when an attribute from session is removed which you feel is very important, you might log an error message for debugging purposes.

The even listeners are pretty useful when used appropriately. Well, that's about this chapter. Lets move on to the next one!!!

Previous Chapter: Chapter 21 - Storing & Retrieving Session Objects

Next Chapter: Chapter 23 - Invalidating Sessions

Chapter 21: Storing and Retrieving Session Objects

By now, you are already familiar with what a Session is and what it is used for. In this chapter we are going to see how to:

• Retrieve a session object across multiple requests to the same or different servlets within the same WebApp.
• Store objects into a session object.
• Retrieve objects from a session object.

So, without any further delays, lets get started!!!

Storing & Retrieving Session Objects:

Using the session is easier said that done. Explaining it as paragraphs would be an arduous and not to mention a boring task. So lets take a look at some sample code that will tell us how to achieve session persistence in our code.

Let me remind you that, please pay attention to the code. You can easily overlook/miss many of the nuances of the session usage and that could cost you dearly in the exam.

Example Code 1:

In this below example, we are going to see how to obtain or rather create a new session and use it.
/**
* Return the session associated with this Request
* If it doesn't, then creating one if necessary
*/
public HttpSession getSession(boolean create)
{
if( System.getSecurityManager() != null )
{
PrivilegedGetSession dp = new PrivilegedGetSession(create);
return (HttpSession)AccessController.doPrivileged(dp);
}
return doGetSession(create);
}

private HttpSession doGetSession(boolean create)
{
// Check if Context exists if not, a session cannot exist
if (context == null)
return (null);

// Return the current session if it exists and is valid
if ((session != null) && !session.isValid())
session = null;
if (session != null)
return (session.getSession());

// Return the requested session if it exists and is valid
Manager manager = null;
if (context != null)
manager = context.getManager();
if (manager == null)
return (null);
if (requestedSessionId != null)
{
try
{
session = manager.findSession(requestedSessionId);
} catch (IOException e) {
session = null;
}
if ((session != null) && !session.isValid())
session = null;
if (session != null) {
return (session.getSession());
}
}

// Create a new session if requested & response is not committed
if (!create)
return (null);
if ((context != null) && (response != null) && context.getCookies() &&
response.getResponse().isCommitted())
{
throw new IllegalStateException(sm.getString("httpRequestBase.createCommitted"));
}

session = manager.createSession();
if (session != null)
return (session.getSession());
else
return (null);
}

/**
* Return true if the session identifier
* included in this request came from a cookie.
*/
public boolean isRequestedSessionIdFromCookie()
{
if (requestedSessionId != null)
return (requestedSessionCookie);
else
return (false);
}

/**
* Return true if the session identifier
* included in this request came from the request URI.
*/
public boolean isRequestedSessionIdFromURL()
{
if (requestedSessionId != null)
return (requestedSessionURL);
else
return (false);
}
Actually, above is how your Tomcat server handles your request to create a session object. Now that we know this let us take a look at another example that is going to actually use this session to do something worthwhile.

Example Code 2:

This is quite a long piece of code. In this example, we will be accessing the session, setting some attributes in it as well as getting some. Also, we are accessing the cookies in the request and using them all to print out some stuff in the web browser.

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;


public class TestSessionsServlet extends HttpServlet
{
// The regular doPost method
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doGet(request,response);
}
// The regular doGet method
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException
{

// Get the session associated with this request
// A new session would get created if it doesn't exist
HttpSession session = request.getSession(true);

// Set some value into the session as attribute
session.setAttribute("sessionId", new Integer(22));

// Try to read some data from the Session
String cookieName = request.getParameter("cookiename");
String cookieValue = request.getParameter("cookievalue");

// It is always a good idea to check for null if a value is
// picked up from the session. If the value you are looking
// for doesn't exist, you will end up with
// a NullPointerException
if (cookieName != null && cookieValue != null)
{
Cookie cookie = new Cookie(cookieName, cookieValue);
response.addCookie(cookie);
}

// Write some stuff on the browser
PrintWriter out = response.getWriter();
response.setContentType("text/html");

out.println("< html >");
out.println(" < head >");
out.println(" < title >Session Detail Report< / title >");
out.println(" < / head >");
out.println(" < body >");
out.println(" < center >");
out.println(" < h2 >Session Detail Report< / h2 >");

String url=request.getScheme()+ "://"+request.getServerName()+
":"+request.getServerPort()+ request.getRequestURI();

out.println(" < table width=\"100%\" border=\"1\" + " cellspacing=\"0\" cellpadding=\"1\" >");
out.println(" < tr >");
out.println(" < td colspan=2 >"+url+"< / td >");
out.println(" < / tr >");
printVoid(out);
out.println(" < tr >");
out.println(" < td colspan=2 >");
out.print("< form action=\""); out.println(url + "\" method=POST >");
out.println("Attribute Name:< input type=text "+"length=20 name=cookiename > < br >");
out.println("Attribute Value:< input type=text"+"length=20 name=cookievalue > < br >");
out.println("< input type=submit >< / form >");
out.println(" < / td >");
out.println(" < / tr >");

printHeader(out,"Cookies in this request:");

// Get all cookies from the Request
Cookie[] cookies = request.getCookies();

if (cookies!=null)

for (int i = 0; i < cookies.length; i++) {

Cookie cookie = cookies[i];

printValue(out,cookie.getName(), cookie.getValue());

}

printVoid(out);


printHeader(out,"Session Details:");

SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss.SSS z");

printValue(out,"Requested Session Id:", request.getRequestedSessionId());

printValue(out,"Current Session Id:", session.getId());

printValue(out,"Session Created Time:",

format.format(new Date(session.getCreationTime())));

printValue(out,"Session Last Accessed Time:",

format.format(new Date(session.getLastAccessedTime())));

printValue(out,"Session Max Inactive " + "Interval Seconds:", Integer.toString(session.getMaxInactiveInterval()));

printVoid(out);


printHeader(out,"Session values:");

Enumeration enum = session.getAttributeNames();

while (enum.hasMoreElements())

{

String key = (String) enum.nextElement();

Object val = session.getAttribute(key);

printValue(out,key,val.toString());

}

printVoid(out);


out.println(" < / td >");

out.println(" < / tr >");

out.println(" < / table >");

out.println(" < / body >");

out.println("< / html >");

out.flush();

}


// Utility methods
public void printHeader(PrintWriter out, String header)
{
out.println(" < tr >");
out.println(" < td bgcolor=\"#999999\" "); out.println(" "colspan=\"2\" >");
out.println(" < b >"+header+"< / b >");
out.println(" < / td >");
out.println(" < / tr >");
}

public void printValue(PrintWriter out, String key, String val)
{
if (val!=null) {
if (val.length()>255)
val=val.substring(0,128)+" (... more)";
}
out.println(" < tr >");
out.println(" < td bgcolor=\"#cccccc\" >"+ key + "< / td >");
out.println(" < td bgcolor=\"#ffffff\" >"+ val + "< / td >");
out.println(" < / tr >");
}

public void printVoid(PrintWriter out)
{
out.println("< tr > < td bgcolor=\"#ffffff\" "+"colspan=\"2\" > < / td >< / tr >");
}
}

You can do a lot more with the details above but to keep it simple, we aren’t attempting anything complicated since this is one of our first examples of using Sessions.

The output of the above servlet would vary based on time and the list of attributes that are already existent in the Session.

It would be a good exercise to deploy this servlet in your local tomcat server instance and observe the output. So, I am not going to paste the resultant browser output here. Sorry about that :) but you will definitely thank me for not doing it because, this exercise will help you nicely…

Previous Chapter: Chapter 20 - Introduction to Session Management

Next Chapter: Chapter 21 - Session Event Listeners

Chapter 20: Introduction to Session Management

In one of the previous chapters, we saw what a Session is, what its purpose is and how it is used. In fact, one of our readers even posted a comment stating that the description was very simple and did not cover the full length and breadth of Session Management. Well my friends, that was just the introduction and in the next few chapters, I will probably bore you to death with the details of Session Management.

So, lets get started!!!

Why do we need a Session?

When one page needs to share information with another, the scope of the data broadens beyond processing a single request. This is because, when a response gets committed, all the data that was held in the request that generated that response is destroyed. So, if you want that data in another page, you will be looking at a blank request object with no data in it. When such a need arises, you must send the data from one page to the server and from the server to the next requested page, whether it be the same page or another page altogether. There are several ways to share state information between requests. However, the primary or the easiest way is to use sessions.

How Do Sessions Work?

The container generates a session ID. When you create a session, the server saves the session ID on the client's machine as a cookie. If cookies are turned off then it appends the ID in the URL. On the server, whatever you add to the session object gets placed in server memory—very resource intensive. The server associates that object in memory with the session ID. When the user sends a new request, the session ID is sent too. The server can then match the objects in its memory with that session ID. This is how we maintain client state.

What are Cookies?

In the previous paragraph about how sessions work, we used the term cookies. A cookie is a tiny text file that is maintained by the browser to do things like store unique IDs. They are normally small (~1KB) and saved in the OS cookie directory or folder. There are numerous browsers that handle cookies in various ways. You can go to c:\documents and settings\your login and search for cookies folder and try seeing what kind of files are placed in it by your browser.

In the old days they were used for all sorts of things, including storing personal data like passwords. The popularity of doing so has waned. Today, especially with servlets, it is better to store most information in sessions than cookies. But it is still important to understand cookies before discussing sessions.

As you can see in the image above, there are many cookies on my machine. Those shown are only a few that have been created on my Windows 7 Sony VAIO Laptop. Originally, folks put actual data like names and addresses in cookies because there wasn't anywhere else to save these valuable pieces of data. Today, the information in a cookie is primarily an identifier of sorts.

Vendors implement session IDs differently. Let us dig into Tomcat to see how it handles sessions IDs. The following snippet, edited for clarity, is how a session ID is generated:

/**
* Generate and return a new session identifier.
*/
protected synchronized String generateSessionId() {

// Generate a byte array containing a session ID
Random random = getRandom();
//int SESSION_ID_SIZE= 16;
byte bytes[] = new byte[SESSION_ID_SIZE];
getRandom().nextBytes(bytes);
bytes = getDigest().digest(bytes);

// The remainder of routine converts
// the byte array to a String of hexadecimal digits.

// This returns something like:
// 62A027E37975F305B07555859780E423
// see Listing 6.6
return (result.toString());
}

Web sites keep track of your activities (such as a shopping cart) with a standard session ID, which assigns each visitor a unique, random number. The servlet specification doesn't address how browsers are supposed to store the session ID. Some browsers store it in memory (but send/receive in request/response header as a cookie), while most store it in a cookie file. For example, when I recently visited Amazon, its servers sent my browser a new session ID which was stored in a cookie file called administrator@amazon[1].txt. In this cookie was the following session ID, among other things like date timestamp:

session-id
002-0150365-1700034
amazon.com/

Cookies have been the target of privacy advocates since the beginning of the internet. Cookies are now used for many things, including the suspicious tracking of your activities as you surf the Internet. Some people call the use of cookies to track activity Web bugs. Some companies are paid to monitor you as much as possible to create a profile. And since that is not in the scope of the exam, we arent going to bother much about them.

Most of the cookies on our machines are not used for anything sinister. You can thwart all this by turning off cookies and images. You can do this in IE by going to View -> Internet Options -> Advanced -> selecting Prompt before accepting Cookies, and clicking OK.

In fact, cookies are used for good far more often than bad. For example, when I go to Amazon.com, I get a familiar view because they remember what I did on my last visit. Amazon can do that because it placed a file on my machine called administrator@amazon[1].txt (the browser actually does this) containing this:

session-id
432-5447995-1125358
amazon.com/
0
4322765824
89901156
321345632
79444758
*
session-id-time
8731881600
amazon.com/
0
9985765824
44191156
185745632
09789758
*
ubid-main
0883061-5210078
amazon.com/
0
6796341376
69581269
777869456
29476039
*
x-main
3xBkjhwcqmPgTz7hgffU8UoFvMDSWX
amazon.com/
0
7896341376
1969969
939053232
9770408
*

I like the idea of Amazon tracking my activities. They are open about it and I can stop them any time I wish. But, it becomes problematic when companies do it stealthily or use it to trouble you. In this case Amazon is a genuine website and I seriously have 0 problems with them saving a cookie in my laptop. Afterall, it is going to help me the next time I visit their site so I practically have no issues with it.

The following are the four most frequently used methods for persisting data between views:
• Field-field: Value of a field in a request is copied to value of same field in response.
• Hidden form field: Data is placed in the HTML in a hidden form field.
• Query string: Some data is appended to the query string or a hyperlink in the HTML.
• Cookie: A small text file created by the browser that stores data sent by the server.

These four approaches are the ones most often used; however, session technology does more for you. The following section describes how Java uses sessions to help you maintain client state.

Using Session Objects

The HttpSession object is very powerful and has many features. Before we dig deep into the world of Sessions, let us take a look at the important methods they have so that we can use them effectively.

getAttribute(java.lang.String name) - Returns an Object associated with that name that was stored in the session object.
getAttributeNames() - Returns an Enumeration object that lists the names of the objects stored in the session object.
getCreationTime() - Returns a long containing the date stamp of creation.
getId() - Returns the id of the session as a String representing the unique identifier assigned to this session.
getLastAccessedTime() - Returns a long containing the date stamp of the last time the session was accessed.
getMaxInactiveInterval() - Returns an integer representing the maximum time interval, in seconds, that the servlet container will keep this session open between client accesses.
invalidate() - This destroys a session. It can't be referenced after this method has been called.
isNew() - This tells you whether the client knows about the session. In other words, the has session been created by the server, but the client hasn't acknowledged receiving the session ID yet.
removeAttribute(java.lang.String name) - This removes an attribute. It deletes it from the session object.
setAttribute(java.lang.String name, java.lang.Object value) - You use this method to add objects to a session.
setMaxInactiveInterval(int interval) - Specifies the time, in seconds, between client requests before the servlet container will invalidate this session.
getValue(java.lang.String name) - Returns an Object associated with that name that was stored in the session object. As of Version 2.2, this method is replaced by getAttribute(). The getAttribute() method will be on the exam, not this one, but it is here for completeness.
getValueNames() - Returns a String array with a list of names associated with the objects added to a given session. As of Version 2.2, this method is replaced by getAttributeNames(). The getAttributeNames() method will be on the exam, not this one, but it is here for completeness.
putValue(java.lang.String name, java.lang.Object value) - You use this method to add objects to a session. This has been deprecated. As of Version 2.2, this method is replaced by setAttribute(java.lang.String, java.lang.Object). The setAttribute() method will be on the exam, not this one, but it is here for completeness.
removeValue(java.lang.String name) - This removes a value, but retains an attribute name in the session. The name is valid but the object is null. This has been deprecated. As of Version 2.2, this method is replaced by removeAttribute(). The removeAttribute() method will be on the exam, not this one, but it is here for completeness.

The preceding methods are the ones that will appear on the exam. For the moment, just relax and don't worry about how and when to use these methods. That is exactly what I am going to explain in the subsequent chapters.

Previous Chapter: Self Test - Chapters 6 to 19

Next Chapter: Chapter 21 - Storing & Retrieving Session Objects

Wednesday, March 23, 2011

Self Test: Chapters 6 to 19

Questions:

Question 1: Which of the following methods are defined in the Servlet interface?
A. init()
B. service()
C. finalize()
D. destroy()

Question 2: Which of the following objects are passed to a servlet's service() method?
A. ServletRequest
B. HttpServletRequest
C. ServletResponse
D. HttpServletResponse

Question 3: By default, how many instances of a servlet are created by a Servlet Container?
A. One
B. One per request
C. One per session
D. None of the above

Question 4: Which of the following exceptions are defined by the Servlet API?
A. ServletException
B. InitializationException
C. UnavailableException
D. ServletContextException

Question 5: Which of the following are used by Servlet Containers to maintain session information?
A. cookies
B. hidden form fields
C. HTTPS protocol information
D. URL rewriting

Question 6: Which of the following event listeners are defined by the Servlet API?
A. HttpSessionBindingListener
B. HttpSessionEventListener
C. HttpSessionParameterListener
D. HttpSessionAttributeListener

Question 7: Which of the following methods are defined by the RequestDispatcher interface?
A. dispatch()
B. include()
C. redirect()
D. forward()

Question 8: Which of the following is the name of the cookie used by Servlet Containers to maintain session information?
A. SESSIONID
B. SERVLETID
C. JSESSIONID
D. CONTAINERID


Answers:

Answer 1: C. The finalize() method is not defined by the Servlet interface.

Answer 2: A, C. ServletRequest and ServletResponse methods are passed to the service() method.

Answer 3: A. By default, only one instance of a servlet is created by a Servlet Container.
Answer 4: A, C. The Servlet API defines ServletException and UnavailableException.

Answer 5: A, C, D. Hidden form fields are not used by Servlet Containers to maintain session information..”
Answer 6: A. Only HttpSessionBindingListener is defined by the Servlet API.

Answer 7: B, D. The RequestDispatcher interface defines the include() and forward() methods.
Answer 8: C. The JSESSIONID cookie is used by Servlet Containers to maintain session information.

Previous Chapter: Quick Recap - Chapters 6 to 19

Next Chapter: Chapter 20 - Introduction to Session Management

Quick Recap: Chapters 6 to 19

Let us quickly go through what we learnt in the previous chapters…

Request Handling Basics:

• The HTTP methods GET, POST, and PUT are how browsers and Web servers trade data with each other
• The GET retrieves a page without providing much information, while a POST can package huge amounts of information with its request
• The most important objects in the servlet process are the request and response objects
• The request parameters for the servlet are the strings sent by the client to the Servlet Container. The container parses the request and puts the information in a HttpServletRequest object which is passed to the servlet
• The container wraps the response parameters with the HttpServletResponse object which is passed back to the container

Scope:

• When something has Context scope it is application-wide and all users can share data
• Session scope means one user can share data across page views, but other users can't
• Request scope restricts data to only that page


Servlet Lifecycle:

• The init() method is used to initialize the Servlet
• The service() methods (doGet(), doPost() etc) get invoked everytime a user request gets submitted
• The destroy() method is used to kill/invalidate the Servlet once it is no longer required.


Key Terms we Learnt:

The key terms we learnt and understood in these chapters were:

1. Redirection
2. Servlet Life-Cycle
3. Servlet Forwarding and Includes
4. Servlet attribute
5. Context parameters
6. Application session
7. listeners

Previous Chapter: Chapter 19 - Listeners & Interfaces in the Web Context

Next Chapter: Self Test - Chapters 6 to 19

Tuesday, March 22, 2011

Chapter 19: Listeners & Interfaces in Web Context

We have seen a lot of things related to a web application like the HttpRequest, ServletContext etc. there are a lot of listeners and interfaces that are part of any J2EE applications life. In this chapter we are going to take a look at them.

So, lets get started!!!

What are Listeners Used For?

Listeners are a useful mechanism by which we can monitor and react to servlet events by defining the appropriate listener objects. These objects have methods that the container would invoke when the life-cycle event occurs. To make this happen, you define a listener class by implementing a listener interface. The container would invoke the listener method and pass it information about that event.

For ex: When the HttpSessionListener interface is implemented, the methods will be passed an HttpSessionObject

What are these Listeners?

There are many different types of Listeners that are available for us to use. The listener we can use depends on the purpose it serves. The Listeners and their purpose are as follows:

1. When a Servlet is Initialized or Destroyed
     a. javax.servlet.ServletContextListener
     b. contextDestroyed(ServletContextEvent sce) Notification that the servlet context is about to be shut down
     c. contextInitialized(ServletContextEvent sce) Notification that the Web application is ready to process requests
2. When a Context attribute is added/removed or replaced
     a. javax.servlet.ServletContextAttributeListener.
     b. attributeAdded(ServletContextAttributeEvent scab) Notification that a new attribute was added to the servlet context.
     c. attributeRemoved(ServletContextAttributeEvent scab) Notification that an existing attribute has been removed from the servlet context.
     d. attributeReplaced(ServletContextAttributeEvent scab) Notification that an attribute on the servlet context has been replaced
3. When a session is initialized or destroyed
     a. javax.servlet.http.HttpSessionListener.
     b. sessionCreated(HttpSessionEvent se) Notification that a session was created.
     c. sessionDestroyed(HttpSessionEvent se) Notification that a session became invalid or timed out.
4. When a session attribute is added/removed or replaced
     a. HttpSessionAttributeListener.
     b. attributeAdded(HttpSessionBindingEvent se) Notification that an attribute has been added to a session.
     c. attributeRemoved(HttpSessionBindingEvent se) Notification that an attribute has been removed from a session.
     d. attributeReplaced(HttpSessionBindingEvent se) Notification that an attribute has been replaced in a session

A Sample Listener Class

Let us now take a look at a sample class that is going to listen for context initialization and destruction. The attribute StartDate is set when the container initializes the application. Then when the application quits, the same attribute is logged and then deleted. This is just a simple example so we arent doing anything major here. But in realtime, we may end up putting a lot more code in these methods than what you see below…

Code:

import java.util.Date;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public final class ContextListener
implements ServletContextListener
{
public void contextInitialized(
ServletContextEvent event)
{
ServletContext context = event.getServletContext();
context.setAttribute("StartDate", Date);
}

public void contextDestroyed(ServletContextEvent event)
{
ServletContext context = event.getServletContext();
Date startDate = context.getAttribute("StartDate");
customLog(startDate);
context.removeAttribute("StartDate");
}
}

Similarly we can have classes that listen for various other events and handle them appropriately…

Previous Chapter: Chapter 18 - Using Request Dispatcher

Next Chapter: Quick Recap - Chapters 6 to 19

Chapter 18: Using a RequestDispatcher

The request dispatcher is an important tool for any J2EE developer who is building a web application that involves multiple JSPs and Servlets. In this chapter, we are going to look at it in detail.

So, lets get started!!!

The RequestDispatcher

The RequestDispatcher is a useful tool. You can perform programmatic server-side includes or route the whole request to another servlet or JSP with a forward. The purpose of the request dispatcher is to direct control from one jsp/servlet to another so that the application can take a course of action that would help complete the current user request.

Getting the Request Dispatcher

The request dispatcher can be obtained in 3 ways. They are:
1. ServletContext.getRequestDispatcher(java.lang.String)
2. ServletContext.getNamedDispatcher(java.lang.String)
3. ServletRequest.getRequestDispatcher(java.lang.String)

The first two ways are getting the dispatcher from the servlet context. Either way of invoking returns a RequestDispatcher object that acts as a wrapper for the named servlet.

Whereas, the third way uses the servlet request. You can use a relative pathname here whereas with the servletcontext we need to use the absolute pathname.

Exam Trivia:
We need to be careful while using the paths. If the path begins with a “/”, it is interpreted as relative to the current context root. You will get a null if the servlet container cannot return a RequestDispatcher. Be sure to use the correct path name and to spot inconsistencies in the code in case the exam puts one in front of you.

Purpose of the RequestDispatcher:

The RequestDispatcher object can be used to forward a request to the resource or to include output from the resource in a response. The specification allows the resource to be dynamic or static. If it is dynamic, such as a servlet, the container will invoke that servlet, and then take the output and include it. If it is static, such as a text file, then the container will include the text as it is.

Lets now look at some sample code as to how the RequestDispatcher can be used.

Sample Code 1:

public void doGet (HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
try {
getServletConfig()
.getServletContext()
.getRequestDispatcher("/SomeExample")
.forward(request, response);
} catch (Exception ex) {
ex.printStackTrace ();
}
}

The above code can be used to forward the control to the SomeExample servlet and include the contents of its output as part of this requests response back to the browser.

Sample Code 2:

RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher(path);
if (dispatcher == null)
{
out.println(path + " not available");
return;
} else
{
dispatcher.include(request, response);
}

You can also include contents from a static page or another servlet in your response. The above code is how you can do it.

Did you notice the difference in the above 2 examples?

If you did not, just scroll up and see the code again. In example 1 I had used forward whereas in example 2, include is used. There are a few characteristics of these two methods.
1. The ServletRequest’s path elements and parameters remain unchanged from the caller’s
2. The included servlet cannot set headers
3. The servlet cannot change the response status code
4. The best way to send information from the calling servlet to the called servlet is using a query string or a better way would be to use the setAttribute() to set values into the request object and use it in the target servlet.
5. And finally, there is also a matter of timing that we need to consider. You can call an include anytime, but the forward has to be called before the response is committed. Otherwise you will end up getting an IllegalStateException.

Regarding the forward method, one reason you may want to use it is so you can dedicate a servlet as the controller. In this way, the controller can filter, preprocess requests, and manage the transaction. The gotcha here is once a servlet forwards a request, it loses control. The controller has no capability to regain access directly. You can create an architecture where requests are returned (forwarded back by a slave servlet), but the native functionality isn't helpful for this.

There is another problem which you need to remember for the exam. When you use the forward method, the URL in the address bar doesn't change. The client loses path information when it receives a forwarded request. That means all relative URLs in the HTML become invalid. Your browser will consider the links broken. Sometimes this doesn't matter, but when it does, you can use sendRedirect() instead.

Exam Trivia:
ServletContext.getRequestDispatcher()— This method uses absolute paths.
ServletRequest.getRequestDispatcher(String path)— The path may be relative, but cannot extend outside current servlet context.
ServletRequest.getNamedDispatcher(String name)— This name is the name of the servlet for which a dispatcher is requested, and is in the web.xml file

Previous Chapter: Chapter 17 - Servlet Lifecycle

Next Chapter: Chapter 18 - Listeners & Interfaces in Web Context

Saturday, March 19, 2011

Chapter 17: Servlet Lifecycle

In the previous few chapters, we saw the request, application and context scope. About, how data can be saved and passed on from one screen to another. Something we havent seen yet is about the servlet life cycle. Well, that is exactly what this chapter is for.

So, lets get started!!!

The Servlet Lifecycle

The servlets life cycle begins when it gets initialized and the servlet is alive as long as it needs to be while it services requests and then it gets killed when it is no longer required. The usual order in which the three important methods of the servlet get called are:
1. init()
2. service() and then
3. destroy()

Exam Trivia:

One of the most common questions that can test your knowledge about Servlets is about when the init() method gets called. Knowledge of the servlets lifecycle is crucial to answering these kind of questions. You need to remember that the init() method may be called when the server starts, when it is first requested and sometimes the container management console will allow you to call it as part of server administration. The exam expects you to know that the init() method will only be called once per servlet instance. It is not used to receive or send information back to the server but, it throws a ServletException to the container that calls the servlet in case anything goes wrong.


The init method is called first, the first time the servlet is invoked. This happens one time and I mean only one time. However, the service method is called every time a servlet is requested by some user action on a web page. Finally, the destroy method is called one time and I mean again one time, upon the removal of the servlet from memory due either to explicit removal or lack of use (for example, the session expires).

You can configure the container to load certain servlets upon startup ( in web.xml), but most of them will be loaded upon first request. (Don’t worry right now about the web.xml because it is one of the important topics we will be covering in detail at a later point of time) Either ways, the init method is called first. We need to place in this method things you will use across requests, like database connections, and class member values such as finalized constants.

The destroy() method, like init(), is called only once. It is called when the servlet is taken out of service and all pending requests to a given servlet are completed or have timed-out. This method is called by the container to give you a chance to release resources such as database connections and threads. You can always call super.destroy() (GenericServlet.destroy()) to add a note to the log about what is going on. You might want to do this even if only to place a timestamp in there.

WARNING

DESTROY() is not called if the container crashes! You should log activity from somewhere other than the destroy() method if a given piece of information is essential, but might not be logged if the logging functionality is placed in the destroy() method. This is because the destroy() method is not called if the Servlet Container quits abruptly (crashes).

In the below image you can see that, the service methods are the only onces that get called everytime the user performs an action through the web browser. The init and destroy methods get invoked once when the servlet is initialized or destroyed.



Previous Chapter: Chapter 16 - Servlet Context

Next Chapter: Chapter 18 - Using Request Dispatcher

Thursday, March 17, 2011

Chapter 16: Servlet Context

In the previous chapter, we saw how data can be stored and utilized per user session. The session is specific to a users navigation of a website and is not shared among users. If you want the system to retain some information that needs to be shared among various users of the system, we need to user the Context. In this chapter, we are going to see what the context is and what are the methods that are available for us to use.

So, lets get started!!!

The Servlet Context

A Web application includes many parts. It is more than just one servlet or JSP. Numerous JSPs and one or more Servlets and other supporting java classes together form the web application. To help manage an application, you will sometimes need to set and get information that all of the servlets share together, which we will refer to as context-wide.

For Example, if you want a single name using which you can refer to the application, you can set it in the servlet context and have it shared across all instances that use the application.

Ex Code:
public void init(ServletConfig config) throws ServletException
{
super.init(config);
// Get the Context
ServletContext context =config.getServletContext();
// Set the attribute
context.setAttribute(“appName", "My Test App");
}

Any time you want, you can refer to this attribute in the context and get its value like below:

String appName = context.getAttribute(“appName”);

After the above line of code, the variable appName will have the value “My Test App”

Methods in the Servlet Context

Apart from setting and getting custom attributes used for our application, the context also contains various methods that we can use to retrieve specific information about the application and other aspects. They are:

getAttributeNames() - Returns an Enumeration object containing the attribute names available within this servlet context.
getContext(String uripath) - Returns a ServletContext object that corresponds to a specified URL on the server.
getInitParameter(String name) - Returns a string containing the value of the named context-wide initialization parameter, or null if the parameter does not exist.
getInitParameterNames() - Returns the names of the context's initialization parameters as an Enumeration of string objects, or an empty Enumeration if the context has no initialization parameters.
getMajorVersion() - Returns the major version as an int of the Java Servlet API that this Servlet Container supports.
getMimeType(java.lang.String file) - Returns the MIME type as a string of the specified file, or null if the MIME type is not known.
getMinorVersion() - Returns the minor version as an int of the Servlet API that this Servlet Container supports.
getNamedDispatcher(String name) Returns a RequestDispatcher object that acts as a wrapper for the named servlet.
getRealPath(String path) - Returns a string containing the real path for a given virtual path.
getRequestDispatcher(String path) Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path.
getResource(String path) - Returns a URL to the resource that is mapped to a specified path.
getResourceAsStream(String path) - Returns the resource located at the named path as an InputStream object.
getServerInfo() Returns the name and version as a String of the Servlet Container on which the servlet is running.

So, as you can see, the context is extremely powerful and useful for any J2EE developer…

Previous Chapter: Chapter 15 - Session

Next Chapter: Chapter 17 - Servlet Life Cycle

Tuesday, March 15, 2011

Chapter 15: The Session

In the previous chapter we took a look at how the HTTP Request can help us move data from the JSP to the Servlet and vice versa and the methods that are available in the Request object that would help us handle the data it carries.

In this chapter, we are going to look at the Session which is a super-set of the request and can contain data that needs to be retained across different pages.

So, lets get started!!!

The HTTP Session:

The Session is the place where data can be stored and retrieved across multiple hits from the same browser for a certain period of time. For example, lets say you want to login to your online banking website and the browser asks you to enter your login id and password after every click? It would be irritating isn’t it?

Exactly yes.

Thankfully we have the Http session.

When we logon to our bank website and enter our login id and password, the application saves our credentials in the session and uses it when we navigate between screens on the banks website.
Note: For reasons of safety and security, usually sessions in sensitive websites like a bank website or a stock brokers site, the session expires automatically after 5 minutes of inactivity or if the user presses the back or refresh buttons.

Getting the Session Object:

The session object can be obtained from the Request using the below line of code:

HttpSession session = request.getSession();


Setting & Getting Attributes from the Session:

We can set and retrieve attributes from the session using the setAttribute & getAttribute methods.

Ex:

session.setAttribute(“Key”, value); //Setting the value

Object obj = session.getAttribute(“Key”); //Getting the value

Here, “Key” is the identifier that will be used to locate the value saved in the session. The “Key” can be used to retrieve the value using the getAttribute() method.

Other Session Methods:

Some other methods available in the Session are:
1. getId() – Every session has a unique id and this method is used to get that id
2. getCreationTime() – To find out when the session was created
3. getLastAccessedTime() – To find out when the session was accessed last
4. getAttributeNames() – To retrieve all the values stored in the session as an Enumeration


To wrap up, sessions are what you can use to track a single user over a short time period (say 5 or 10 mins usually). You get the session object (HttpSession) from the request object. To track multiple users in your application, you can use the Context. Don't worry, that's our next stop…

For now, this chapter is over!!!

Previous Chapter: Chapter 14 - The Request Object

Next Chapter: Chapter 16 - Servlet Context
© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers