Chapter 4: Servlet Container Model

Objectives

This chapter covers the following objectives listed by Sun in "Section 1The Servlet Model" and "Section 3The Servlet Container Model."

1.1 For each of the HTTP methods, GET, POST, and PUT, identify the corresponding
method in the HttpServlet class.

The HTTP methods GET, POST, and PUT are how browsers
and Web servers communicate the purpose of communication. A GET simply
wants to retrieve a page without providing much information. A POST,
however, can package lots of form or file information with its request. A
PUT is for uploading a file. The HttpServlet class has a
corresponding method for each HTTP method, including doGet(), doPost(),
and doPut().

1.2 For each of the HTTP methods, GET, POST, and HEAD, identify triggers
that might cause a browser to use the method, and identify benefits or functionality
of the method.

This objective asks you to understand the events associated with each type
of request. For example, clicking a hyperlink will send a GET request
to a Web server, but clicking a Submit button (when the action is set to "post")
will send a POST request.

1.3 For each of the following operations, identify the interface and method
name that should be used to

Retrieve HTML form parameters from the request

Retrieve a servlet initialization parameter

Retrieve HTTP request header information

Set an HTTP response header; set the content type of the response

Acquire a text stream for the response

Acquire a binary stream for the response

Redirect an HTTP request to another URL

This objective is huge. It encompasses the heart of a servlet process,
especially 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 an HttpServletRequest
object which is passed to the servlet. Going the other way, the container
wraps the response parameters in an HttpServletResponse object
which is passed back to the container. The associated chapter section later
in this chapter ("Overriding HttpServlet GET, POST,
and PUT methods") goes into much detail on the methods involved.

1.4 Identify the interface and method to access values and resources and
to set object attributes within the following three Web scopes:

Request

Session

Context

This objective addresses the idea of 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.

1.5 Given a life-cycle method, identify correct statements about its purpose
or about how and when it is invoked. These methods are

init

service

destroy

The container manages the servlet life-cycle. This part of the chapter
explains, with examples, how the container initializes a servlet with a
call to the init() method. Then it calls the service()
method upon every request. Finally, when the servlet is about to be removed
from memory, the container calls its destroy() method. This gives
the servlet one last chance to clean up resources.

1.6 Use a RequestDispatcher to include or forward to a Web resource.

The RequestDispatcher object is the servlet forwarding mechanism.
You will see in the section "Servlet Life-cycle" how you can transfer
processing of the request from one servlet to another (which the browser will
be unaware of). This is how a servlet can pass the request to some other Web
component within the same Web container.

3.1 Identify the uses for and the interfaces (or classes) and methods to
achieve the following features:

Servlet context initialization parameters

Servlet context listener

Servlet context attribute listener

Session attribute listeners

These elements let you get and monitor servlet attributes. Not only can
you get them and change them too, but you can actually put in place behavior
to occur when an attribute changes. The listeners are event-driven triggers.
When an attribute changes, special targeted methods are called. In them,
you can define special actions, such as adding a note to the log every time
the user count changes (perhaps a context attribute called counter).

3.3 Distinguish the behavior of the following in a distributable:

Servlet context initialization parameters

Servlet context listener

Servlet context attribute listener

Session attribute listeners

As explained in the previous objective, these elements let you get and
monitor Servlet attributes. There is a difference here in that Sun wants
you to understand how this works in a distributable Web application.

Outline

Introduction

Overriding HttpServlet GET, POST, and PUT Methods

GET

POST

PUT

Triggering HttpServlet GET, POST, and PUT Methods

GET

POST

HEAD

Interfacing with HTML Requests

Form Parameters

Retrieving a Servlet Initialization Parameter

Retrieving HTTP Request Header Information

Acquiring a Binary Stream for the Response

Redirecting an HTTP Request to Another URL

Web Application Scope

Request

Session

Context

Servlet Life-cycle

Using a RequestDispatcher

Web Application Context

Context Within a Distributable Web Application

The key to this section of the exam is understanding how servlets implement the Servlet interface, which defines life-cycle methods. The Servlet Container (such as Apache Tomcat) is itself an application that monitors a port on a given IP address. Servlets generate responses to HTTP requests. To do so, the container loads your servlet (if it isn't in memory already) and calls the methods defined in the interface. This is the foundation of servlet and JSP architecture.

There are many methods to know. It is easier if you learn the methods in groups according to theme. For example, write a servlet that has HttpServlet methods which handle all three GET, POST, and PUT types of request.

Each JavaServer Page is transformed into a servlet that is compiled and then loaded. Therefore much of what you learn here applies to the JSP section of the exam too.

Introduction

JSP and servlets have greatly enhanced the way in which you can create and manage Web pages. The difficulty level of coding JSP is between that of coding HTML and pure Java. Servlets are pure Java. The idea behind having both is providing a way for non-programmers to contribute functionality through JSP. You can "program" a JSP page almost as easily as you can write an HTML page. For simple tasks like displaying the current date, you write a normal HTML page and add only a small amount of Java as a scriptlet. For big tasks like processing a shopping cart, you use JSP as the mediator between the Web form and a component(s) (bean or servlet) that has all the horsepower. Most of the code in a Web application will go into servlets. The JSP portion is a soft front end to the application that, typically, marketing can use comfortably.

There is a lot that happens when a servlet is invoked. This chapter covers much material that explains each step of the process. At this point, it will help to provide an overview of what happens in a typical JSP/servlet request. The sequence of events starts with a browser sending a request to a Web server. The server hands the request to a Servlet Container. The container loads the servlet (if it isn't already loaded), instantiates a request and response objects, and then hands these objects to the servlet by calling first its init() method, then its service() method, and lastly the destroy() method. The service() method will typically call one of the doXXX() methods such as doGet().

All these steps are covered in detail later in this chapter. Presently, just
review the overall process presented in Figure 4.1.

Let's study an example of a servlet. The following is a fully functioning, albeit trivial, servlet example. Listing 4.1 represents all that is required to have a complete servlet.

Listing 4.1 showed you an example of a servlet. The code is ordinary, but notice
one small thing about printing to the browser. This example uses PrintWriter
instead of using ServletOutputStream. The former is used for text,
while the latter is used for bytes. See Figure
4.2 for a picture of the output. Listing 4.2 is the HTML the servlet generates
and sends to the browser.

You write a servlet and compile it, and then place it in the appropriate
directory. When the Servlet Container starts, it will preload your servlet
in memory if specified in the web.xml configuration file. If your servlet
is not already loaded (not listed in the web.xml configuration file), its
instance will be created as soon as a request for it is received by the Servlet
Container. The first time it is loaded, the container calls your servlet's
init() method, if there is one. Notice that it gets called only once,
so place one-off functionality in this method (such as database connection,
file object). Now that your servlet is ready, it waits for requests. The container
will call your service() method each time a request is received for
your servlet. The HttpServlet class (which your servlet must extend)
already has this method, so you don't have to write one, but you can
override it. The service() method then passes the request on to the
appropriate method (usually GET for simple requests and POST
to submit data, say a Web page form) such as the doGet() method if
it is a GET request, or the doPost() method if it is a POST
request. The doXXX() methods are the ones you need to override and
where you will spend most of your effort. The servlet processes the request
(code you write in doGet()), returning a response to the container.
The container sends the text of the response back to the browser.

The preceding JSP and servlet examples are part of a Web application. A Web application is a collection of servlets, JSP pages, HTML documents, and other Web resources (such as image files, compressed archives, and other data). This collection may be packaged into an archive or exist as separate files in an open directory structure. Since you have many servlet classes, JSP pages, HTML pages, and other supporting libraries and files for a given Web application, there are many dependencies. These are not trivial to manage. It is vital that all parts go in their correct locations in the Web application archive or in an open directory structure. Once you get the dependencies resolved, it is a good idea to package the collection into a Web application archive, a single file with the .war extension that contains all of the components of a Web application. You can do this using standard JAR tools.

Now, we need to define what is meant regarding deploying a Web application. Normally, Web applications run on only one VM at any one time. When we talk about deploying a Web application, we mean that the collection of files that comprise a Web application is placed into a Web server's runtime (at least one part goes into JVM, which can then link to or grab other parts). What happens if you want to deploy your Web application in a Web farm? In this case, your Web application will run on several VMs simultaneously.

A distributable Web application is written so that it can be deployed in a Web container, distributed across multiple Java virtual machines running on the same host or different hosts. The two keys to making this possible are how you thread the servlets and what you tell the deployment descriptor. With the right combination of these, your Web application will run on several VMs simultaneously. The servlet declaration, which is part of the deployment descriptor, controls how the Servlet Container provides instances of the servlet. Normally, the Servlet Container uses only one instance per servlet declaration. However, for a servlet implementing the SingleThreadModel interface, the Servlet Container may instantiate multiple instances to handle a heavy request load and serialize requests to a particular instance.

In the case where a servlet is marked in the deployment descriptor as distributable and the application implements the SingleThreadModel interface, the container may instantiate multiple instances of that servlet in each VM of the container or across many machines (clustering servlets usually through serialization). The container has a complicated task in managing requests, sessions, and contexts across JVMs. How each vendor accomplishes this is beyond the scope of this book. You do need to know that to convert your Web application into a distributable one, you must implement the SingleThreadModel interface and mark the servlet as distributable in the deployment descriptor (see Chapter 10, "Web Applications," for more about web.xml).

Overriding HttpServlet GET, POST, and PUT Methods

1.1 For each of the HTTP methods, GET, POST, and PUT, identify the corresponding
method in the HttpServlet class.

GET

POST

PUT

This exam objective addresses the most-used feature of servlets, namely, responding to HTTP requests. The exam will have several questions on this topic. These three types of requests dominate browser-server traffic.

The following code is a minimal template showing you how to use the GET, POST, and PUT methods. GET appends data to the URL before the URL is submitted to the server, whereas POST sends the data to the server separately from the URL. GET submissions can only be 1KB in length in most cases, whereas POST submissions can be arbitrarily large. The results of a GET submission can be reliably bookmarked, whereas the results of a POST submission can't. There are several differences between them which are explained later in this section.

These methods are called by the service method (not required in your servlet as it is in HttpServlet, as this method is inherited from HttpServlet). Together they can look like Listing 4.3.

It is the service method that calls the doXXX() methods. While you normally wouldn't override the service method, Listing 4.4 presents a skeleton example of what you could do with it. You might want to preprocess the request before sending it on to the appropriate doXXX() method.

When you write a servlet, this is the one method that you will start with. If this method is all you had in your servlet, it would handle the majority of your Web server's needs regarding this servlet. Notice, that the init() and service() methods involved in a request are already provided by the HttpServlet class, so they don't need to be overridden, although you can do so.

The GET is the most common type of browser request. According to the Hypertext Transfer Protocol standard, the GET method means "retrieve whatever information (in the form of an entity) is identified by the Request-URI." For a full discussion on naming and addressing (URL vs. URI) please see http://www.w3.org/Addressing/. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process." In our example, the test message is the entity.

GET Method

The GET is the most common type of browser request. The GET request is defined by the Internet Society's RFC 2616: Hypertext Transfer ProtocolHTTP/1.1. See section 9.3 of RFC 2616 at ftp://ftp.isi.edu/in-notes/rfc2616.txt.

This method is where your servlet does most of its labor. You could process a simple HTML response or hit a database with a query.

Table 4.1 provides a list of differences between GET and POST requests.

Table 4.1 GET vs. POST Request

GET

POST

Query string or form data is simply appended to the URL as name-value pairs.

Form name-value pairs are sent in the body of the request, not in the URL itself.

The POST method is more sophisticated than a GET request. Normally, a Web form has fields whose names and values are sent to the server in key-value pairs. The POST is designed for posting long messages (for example, to a bulletin board, newsgroup, mailing list); providing a block of data, such as the result of submitting a form; and submitting long data fields to a database (such as a SQL insert of lengthy string). Sometimes the action performed by the POST method doesn't return a standard HTML page. Suppose you updated a database table. The database doesn't send back an HTML confirmation on its own. You would have to wrap the database results in HTML manually. You also have the option of sending back an empty response with a header status of either 200 (OK) or 204 (No Content). A No Content status tells the browser that it shouldn't expect any HTML. You might want to do this if it is software to software interaction and no eyeballs are waiting to see a Web page.

POST Method

The POST is the most sophisticated of the methods covered by this part of the exam. The POST request is defined by the Internet Society's RFC 2616: Hypertext Transfer ProtocolHTTP/1.1. See section 9.5 of RFC 2616 at ftp://ftp.isi.edu/in-notes/rfc2616.txt.

Normally, this method is used to process a form submitted by a browser. You will very likely be looking for form field names and values. For example, the following snippet is how you would grab the value of the field formCountField that the user supplied a value for:

PUT

The PUT type request is a means of uploading files to the server. While uploading is its original intent, I have not seen it used much. Instead, POST is generally used to upload files. The PUT handler has this syntax:

The doPut() method is called by the server (via the service method) to handle a PUT request. Uploading files from a browser has always been difficult. The idea behind the PUT operation is to make uploading straightforward. It is supposed to allow a client to place a file on the server, just like sending a file by FTP. The javadoc for this method warns that when overriding this method, you should leave intact any content headers sent with the request (including Content-Length, Content-Type, Content-Transfer-Encoding, Content-Encoding, Content-Base, Content-Language, Content-Location, Content-MD5, and Content-Range). This method is rarely used, but it is powerful if you need it.

Listing 4.5 is a simplified HTML page that creates a file upload page that will direct the file contents to a servlet.

Listing 4.6 worked when placed in the doPost() method (and the form method of Listing 4.5 is set to post), but did not work in the doPut() method using IE or Opera against Tomcat (version 4). I verified that the doPut() method is called as expected in the servlet. However, even after much tweaking, this file upload code failed when placed in the doPut method as shown previously. If you only change doPut to doPost it works?! Although I need to research this problem with Tomcat, you do need to understand that PUT is used to upload files to a Web server and that this is usually done by non-browser, client-side Web content development tools.

Triggering HttpServlet GET, POST, and PUT Methods

1.2 For each of the HTTP methods, GET, POST, and HEAD, identify triggers
that might cause a browser to use the method, and identify benefits or functionality
of the method.

GET

POST

HEAD

This exam objective focuses on what triggers the events or methods in your servlets. For example, what action can a client take that results in the doGet() method being called in your servlet?

GET

As noted previously, the GET type request is normally used for simple HTML page requests. The types of events that generate this type of request are clicking on a hyperlink, changing the address directly by typing in the address textbox on a browser or application that has HTML functionality, and submitting an HTML form where the method header is set to get as in method=get. Also, a GET request is triggered when selecting a favorite from the Favorites list and using JavaScript to change location.href. Usually the browser is configured to send a GET request even if no method is set explicitly by the HTML.

The benefits of the GET method are

It retrieves information such as a simple HTML page or the results of a database query.

POST

This occurs when a browser or application submits an HTML form with the method attribute set to post as in method=post.

The benefits of the POST method are

It sends information to the server such as form fields, large text bodies, and key-value pairs.

It hides form data because it isn't passed as a query string, but in the message body.

It sends unlimited length data as part of its HTTP request body.

It disallows bookmarks.

HEAD

A browser or application will sometimes send a request to a server just to check the status or get information (for example, "can you handle file upload?") from the server.

The HEAD method returns the same header lines that a GET method would return; however, no body or content is returned. This is often accomplished by calling doGet(), setting the headers but not setting any output, and then returning the response (without any body) to the requester.

The primary benefit of this method is message size. The HEAD method receives and returns very small messages. Therefore it is fast and lightweight on both ends.

Interfacing with HTML Requests

In this section we deal with interfacing with HTML requests: how to process them and how to return a response to one. Since the HTTP client is sending the request, how do you know what it wants? While the container handles things like parsing the request and placing the information into a Request object, sometimes you have manually code processing routines. This section tells you how to write these routines that perform actions such as retrieve HTML form parameters, request headers, servlet initialization parameters, and redirects.

1.3 For each of the following operations, identify the interface and method
name that should be used to

Retrieve HTML form parameters from the request

Retrieve a servlet initialization parameter

Retrieve HTTP request header information

Set an HTTP response header; set the content type of the response

Acquire a text stream for the response

Acquire a binary stream for the response

Redirect an HTTP request to another URL

This is a broad-stroke objective. It is asking you to be familiar with the most important servlet interfaces and their methods. Thankfully, this objective reduces the task from remembering almost 1,000 methods to just a few of them, which happen to be the most interesting ones.

Form Parameters

The interface that defines the form parameter methods is ServletRequest. This interface is implemented by the Web container to get the parameters from a request. Parameters are sent in the query string or posted form data. The four methods associated with getting parameters are

getParameter(String). You use this method if you know the particular parameter name. It returns the value of a request parameter as a string, or null if the parameter does not exist. Use this method when you are sure the parameter has only one value; otherwise use getParameterValues(). Be careful: If you use this method with a multivalued parameter, you won't get an error. You will get the first value in the array returned by getParameterValues().

getParameterMap(). You use this method to create a map of the form parameters supplied with this request.

getParameterNames(). This one returns an Enumeration of string objects containing the names of the parameters contained in this request, or an empty Enumeration if the request has no parameters.

getParameterValues(String). This method returns an array of values as strings, or null if the parameter does not exist. If the parameter has a single value, the array has a length of 1. One of the common uses of getParameterValues() is for processing <select> lists that have their "multiple" attribute set.

Listing 4.7, the following code snippet, demonstrates how you would grab the parameters from a request.

Retrieving a Servlet Initialization Parameter

A Web application includes many parts; it rarely is just one class or file. It can be a combination of JSP pages, servlets, tag libraries, Java beans, and other class files. The Java Virtual Machine creates a memory box for all of these called a ServletContext object which maintains information (context) about your Web application. You access the ServletContext for information about the application state. As the API states, the ServletContext allows you access many types of information. You can get application-level initialization parameters. You can also set and get application attributes, as well as the major and minor version of the Servlet API that this Servlet Container supports. One very interesting capability is to get hold of RequestDispatcher object to forward requests to other application components within the server, or to include responses from certain components within the servlet and to log a message to application log file. The ServletContext object is how you can set, get, and change application (not session) level attributes and talk to the Servlet Container.

Context means application scope. The getInitParameter and getInitParameterNames methods retrieve context-wide, application-wide, or "Web application" parameters. The getInitParameter method returns a string containing the value of the parameter (you provide the name), or null if the parameter does not exist.

Some parameters have no information, so this method will return a string containing at least the Servlet Container name and version number. The getInitParameterNames method retrieves the names of the servlet's initialization parameters as an Enumeration of string objects. If there aren't any, it returns an empty Enumeration. Be careful; don't confuse this with session-wide attributes.

Retrieving HTTP Request Header Information

The request header is where all the details of the request are bundled. This is where the browser specifies the file wanted, date, image file support, and more. Listing 4.9 shows a popular way to display the header parameters by walking through an Enumeration of them.

Figure 4.4
You can retrieve request header information using a servlet.

Acquiring a Binary Stream for the Response

Suppose you want to open a binary file in a browser from a servlet. It isn't text so you have to write the file to the servlet's output stream. Let's practice with a PDF document. First, you get the servlet's output stream with:

ServletOutputStream out = res.getOutputStream();

Next, you set the file type in the response object using one of the standard MIME (Multipurpose Internet Mail Extension) protocols. Several listings of content type names are available on the Internet including one at ftp://ftp.isi.edu/in-notes/iana/assignments/media-types. Then you use an HTTP response header named content-disposition. This header allows the servlet to specify information about the file's presentation. Using that header, you can indicate that the content should be opened separately (not actually in the browser) and that it should not be displayed automatically, but rather upon some further action by the user. You can also suggest the filename to be used if the content is to be saved to a file. That filename would be the name of the file that appears in the Save As dialog box. If you don't specify the filename, you are likely to get the name of your servlet in that box. To find out more about the content-disposition header, check out Resources or go to http://www.alternic.org/rfcs/rfc2100/rfc2183.txt.

Sending a binary stream to the client is not easy. Listing 4.10 will help you do it right.

Redirecting an HTTP Request to Another URL

It often happens that pages move around and a URL becomes invalid. Throwing back a 404 error isn't nice. The response object has the sendRedirect method, which sends a temporary redirect response to the client sending with it a new location URL. You can use relative or absolute URLs, because the Servlet Container translates a relative URL to an absolute URL before sending the response to the client.

The two potential problems with this method are sending a bad URL to the client and using this method after the response has already been committed. The bad URL will look bad, but not produce an error. The latter, though, will throw an IllegalStateException. Furthermore, after using this method, the response is committed and can't be written to, or you'll get an error. One nice feature is that this method writes a short response body including a hyperlink to the new location. This way, if the browser doesn't support redirects, it will still get the new link. Use the following syntax for this method:

// Suppose this portion of the server is down.
// Redirect the user to an explanation page.
redirectPath = "./error/notAvailable.html";
response.sendRedirect(redirectPath);

Web Application Scope

This section discusses scope. There are three scopes to worry about for the exam: namely, Request, Session, and Context. Suppose you had to keep track of all your customer visits to your support Web site. Where would you place the counter? You would place it in Context scope. To better understand what I mean, please study the following objective.

1.4 Identify the interface and method to access values and resources and
to set object attributes within the following three Web scopes:

Request

Session

Context

This objective requires you to understand how to set and get name-value attributes at three different levels. The breadth of scope increases from Request to Session to Context, the widest scope.

Table 4.2 provides a definition of the three object scopes of concern under this objective, namely, Request, Session, and Application.

Life of container or explicitly killed (such as container administration action).

The idea here is if you set an attribute (that is, request.setAttribute()), when can you access it? The answer depends on which object was used to the attribute. So, if you set an attribute with the request object, then the scope of that specific attribute is only Request. You can't access it once the request is complete. You can't see this attribute in another request even if it is in the same session. Conversely, any attribute set with the ServletContext object can be seen in all sessions and all requests.

Listing 4.11 is a program that demonstrates how you could use access attributes from the three primary scopes of Request, Session, and Application. You can also use setAttribute() for each of these scopes.

Figure 4.5
You can get attributes with Request, Session, or Application scope.

The previous listing demonstrates how to retrieve attributes from the three primary scopes. Let us now focus on the Request object.

Request

When a user hits a URL with a servlet at the other end, the Servlet Container creates an HttpServletRequest object. It passes this object as an argument to the servlet's service methods (doPut(), doGet(), and doPost()). There is a lot of information in this object, including the login of the user making this request (getRemoteUser()) and the name of the HTTP method with which this request was made (getMethod()). However, this exam objective is restricted to header information. Therefore, you need to know the following HttpServletRequest methods.

The following list of methods summarizes the Request (Interfaces: ServletRequest and HttpServletRequest) methods you need to be familiar with. While, strictly speaking, all are fair game, I marked with an asterisk those that are more likely to be on the exam:

*getAttribute(String name). Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.

*getAttributeNames(). Returns an Enumeration containing the names of the attributes available to this request.

getAuthType(). Returns the name of the authentication scheme used to protect the servlet.

getCharacterEncoding(). Returns the name of the character encoding used in the body of this request.

getContentLength(). Returns the length, in bytes, of the request body if made available by the input stream, or -1 if the length is not known.

getContentType(). Returns the MIME type of the body of the request, or null if the type is not known.

getContextPath(). Returns the portion of the request URI that indicates the context of the request.

getCookies(). Returns an array containing all of the Cookie objects the client sent with this request.

getDateHeader(java.lang.String name). Returns the value of the specified request header as a long value that represents a Date object.

*getHeader(java.lang.String name). Returns the value of the specified request header as a String.

*getHeaderNames(). Returns an enumeration of all the header names this request contains.

getHeaders(java.lang.String name). Returns all the values of the specified request header as an Enumeration of String objects.

getInputStream(). Retrieves the body of the request as binary data using a ServletInputStream.

getIntHeader(java.lang.String name). Returns the value of the specified request header as an int.

getLocale(). Returns the preferred Locale that the client will accept content in, based on the Accept-Language header.

getLocales(). Returns an Enumeration of Locale objects indicating, in decreasing order starting with the preferred locale, the locales that are acceptable to the client based on the Accept-Language header.

*getMethod(). Returns the name of the HTTP method with which this request was made; for example, GET, POST, or PUT.

*getParameter(java.lang.String name). Returns the value of a request parameter as a string, or null if the parameter does not exist.

getParameterMap(). Returns a java.util.Map of the parameters of this request.

*getParameterNames(). Returns an Enumeration of string objects containing the names of the parameters contained in this request.

*getParameterValues(java.lang.String name). Returns an array of string objects containing all of the values the given request parameter has, or null if the parameter does not exist.

getPathInfo(). Returns any extra path information associated with the URL the client sent when it made this request.

getPathTranslated(). Returns any extra path information after the servlet name but before the query string, and translates it to a real path.

getProtocol(). Returns the name and version of the protocol the request uses in the form protocol/majorVersion.minorVersion, for example, HTTP/1.1.

*getQueryString(). Returns the query string that is contained in the request URL after the path.

getReader(). Retrieves the body of the request as character data using a BufferedReader.

getRemoteAddr(). Returns the Internet Protocol (IP) address of the client that sent the request.

getRemoteHost(). Returns the fully qualified name of the client that sent the request.

getRemoteUser(). Returns the login of the user making this request, if the user has been authenticated, or null if the user has not been authenticated.

*getRequestDispatcher(java.lang.String path). Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path.

getRequestURI(). Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request.

getRequestURL(). Reconstructs the URL the client used to make the request.

getRequestedSessionId(). Returns the session ID specified by the client.

getScheme(). Returns the name of the scheme used to make this request; for example, http, https, or ftp.

getServerName(). Returns the host name of the server that received the request.

getServerPort(). Returns the port number on which this request was received.

getServletPath(). Returns the part of this request's URL that calls the servlet.

*getSession(). Returns the current session (HttpSession) associated with this request, or if the request does not have a session, creates one.

*getSession(boolean create). Returns the current HttpSession associated with this request, or, if there is no current session and create is true, returns a new session.

getUserPrincipal(). Returns a java.security.Principal object containing the name of the current authenticated user.

isRequestedSessionIdFromCookie(). Checks whether the requested session ID came in as a cookie.

isRequestedSessionIdFromURL(). Checks whether the requested session ID came in as part of the request URL.

isRequestedSessionIdValid(). Checks whether the requested session ID is still valid.

isSecure(). Returns a boolean indicating whether this request was made using a secure channel, such as HTTPS.

isUserInRole(java.lang.String role). Returns a boolean indicating whether the authenticated user is included in the specified logical "role".

*removeAttribute(java.lang.String name). Removes an attribute from this request.

*setAttribute(java.lang.String name, java.lang.Object o). Stores an attribute in this request.

setCharacterEncoding(java.lang.String env). Overrides the name of the character encoding used in the body of this request.

Several of the HttpServletRequest methods are not mentioned specifically in the objectives, but you should be familiar with them. Listing 4.11 is a program that demonstrates how you would retrieve attributes from the Request object, the main concern in the current exam objective. However, I thought you might also like to see what else you can do with this object. Listing 4.12 uses the Request object's methods to retrieve HTTP request header information (similar to Listing 4.10). Of course, the information you get out of the Request object has only Request scope.

Session

A Session is made up of multiple hits from the same browser across some period of time. The session scope includes all hits from a single machine (multiple browser windows if they share cookies). Servlets maintain state with sessions. Listing 4.13 is a modification of a sample servlet that ships with Tomcat. It demonstrates how you can use session attributes.

To summarize, sessions are what you can use to track a single user over a short time. You get the session object (HttpSession) from the request object. To track multiple users over time you must jump to context, covered next.

Context

A Web application includes many parts; it rarely is just one class or one JSP. To help manage an application, you will sometimes need to set and get information that all of the servlets share together, which we say is context-wide. An example would be using a login servlet to create an application-level attribute such as application name like so:

Besides setting and retrieving your custom attributes, you can get additional information from the Servlet Container, such as its major and minor version, the path to a given servlet, and more. The following summarizes the additional methods you might use:

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.

Servlet Life-cycle

1.5 Given a life-cycle method, init, service, or destroy, identify correct
statements about its purpose or about how and when it is invoked.

The servlet life-cycle is not obvious. The container calls three methodsnamely, init(), service() and destroy()in that order. Ordinarily, that is how the container talks to your servlet. With some containers, you can modify this behavior, but the exam will assume this order.

When is init() called?

A common question on the exam tests your understanding of when init()
is called. Knowledge of a servlet's life-cycle is crucial to answering
these types of questions. Remember, init() may be called when the
server starts (tell web.xml to load servlet upon startup), when first
requested, and sometimes the container management console will allow you to
call it as part of the server administration. The exam expects you to know
that init() will only be called once per servlet instance, that it
is not used to send information back to the browser (HttpServletResponse
is not a parameter), and that it throws a ServletException to the
container that called the servlet if anything goes wrong.

The init method is called first, the first time the servlet is invoked. This happens one time. However, the service method is called every time a servlet is requested. Lastly, the destroy method is called 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 (<load-on-startup/> in web.xml), but most of them will be loaded upon first request. Either way, the init method is called first. 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 (that one with the mentioned destroy() method) 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.

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).

Listings 4.15 and 4.16 are sample Web applications (HTML page and servlet combination) that demonstrate how to use the init(), service(), and destroy() methods, and when they are called. You could combine them and just have one servlet, but there are two pieces here to illustrate the relationship between static and dynamic parts of an application. The first part, Listing 4.15, is the HTML page.

Listing 4.15 HTML Page That Works with Servlet in Listing 4.16 Illustrating
the Relationship

Servlets are loaded in one of three ways. The first way is when the Web
server starts. You can set this in the configuration file. Reload can happen
automatically after the container detects that its class file (under servlet
dir, for example, WEB-INF/classes) has changes. The third way, with some containers,
is through an administrator interface.

The HTML page contains a form with one field for a last name. When submitted, the container takes the lastname field and hands it to the servlet in the request object. This object is where you normally extract requester information. The servlet grabs the lastname, if any, and builds a SQL WHERE clause with it. Then the servlet establishes a connection with the database server (I'm using MS SQL Server) and executes the statement. Then it walks through the resultset getting the data from each field of every row. Finally, it builds the HTML page and sends it off to the client browser. While the database portion is not on the exam, it is an excellent example of how you can take advantage of the methods that are called by the container.

Servlet Synchronizing!

Servlets are run each in their own thread. When the synchronized
keyword is used with a servlet's service() method, requests
to that servlet are handled one at a time in a serialized manner. This means
that multiple requests won't interfere with each other when accessing
variables and references within one servlet. It also means the processing
capabilities of the Servlet Container are reduced because the more efficient
multithreaded mode has been disallowed for a given servlet that has been declared
with the synchronized keyword.

Listing 4.16 is the servlet that queries the database based on the form data. Notice that you can forgo the above HTML file by appending the FirstName parameter to the URL like so: http://localhost:8080/examples/servlet/SearchLastNameServlet?LastName=Fuller. Also, you need to set up a data source with system data source names (DSNs), whether to a data source that is local to your computer or remote on the network.

Listing 4.16 Servlet That Queries a Database Based on Form Input from Listing
4.15

Once you set up a proper System DSN, or use a fully qualified connection string,
the servlet will query the database. Listing 4.15 shows how you can create an
HTML form to call this servlet. The output of the servlet query looks similar
to Figure 4.6.

Listing 4.16 is just an example of when you might invoke the destroy() method. This code example could be improved in two ways. First, it is not thread-safe (statement and resultset variables could be local, not instance variables). That way separate instances wouldn't walk over each other's results. Second, this example doesn't make use of the Data Access Object pattern. You could do better by having separate objects for the Presentation and Database ("separation of concerns") portions of the program. I've lumped it all together here just to demonstrate the section point of how the destroy() method is used.

Using a RequestDispatcher

1.6 Use a RequestDispatcher to include or forward to a Web resource.

The RequestDispatcher is a powerful tool. You can perform programmatic server-side includes or route the whole request to another servlet or JSP with a forward. There are three ways to get the RequestDispatcher. The first two are through the Context, with ServletContext.getRequestDispatcher(java.lang.String) or with ServletContext.getNamedDispatcher(java.lang.String). Either returns a RequestDispatcher object that acts as a wrapper for the named servlet (in web.xml, the Web application deployment descriptor). The final way is with ServletRequest.getRequestDispatcher(java.lang.String). Notice that you can use a relative pathname here. You must use absolutes with ServletContext.getRequestDispatcher(java.lang.String). Be careful with your 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.

A 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 is. Listing 4.17 demonstrates how one servlet can transfer the request to another servlet.

Listing 4.17 Using a RequestDispatcher to Forward a Request to Another Servlet

There are a few characteristics about the forward and include methods. The ServletRequest's path elements and parameters remain unchanged from the caller's. The included servlet cannot set headers. This is a good candidate for a trick question. The servlet cannot change the response status code either (if you try, it will be ignored). The best way to send along information from the calling servlet to the called servlet is using a query string or, even better, using the setAttribute() method to set request object attributes where they are easy to access.

There is a matter of timing to consider. You can call an include anytime, but the forward has to be called before the response is committed. Otherwise you'll throw an IllegalStateException exception.

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 (see Chapter 10, "Web Applications," for more about web.xml).

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. When you run Listing 4.17, you'll notice something missing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, use sendRedirect() instead.

Web Application Context

3.1 Identify the uses for and the interfaces (or classes) and methods to
achieve the following features:

Servlet context initialization parameters.

Servlet context listener.

Servlet context attribute listener.

Session attribute listeners.

Please see the section "Interfacing with HTML Requests,"
earlier in this chapter, where the related objective 1.3 "Retrieve a servlet
initialization parameter" is discussed. Listing 4.8 is especially helpful
here because it demonstrates how to enumerate the context initialization parameter
list.

Regarding listeners, you can monitor and react to servlet events by defining listener objects. These objects have methods that the container invokes when life-cycle events occur. To make this happen, you define a listener class by implementing a listener interface. The container will invoke the listener method and pass it information (methods in the HttpSessionListener interface are passed an HttpSessionEvent) about that event.

Listing 4.18 demonstrates how you could use the initialization and destruction events.

The attribute StartDate is set when the container initializes the application. Then when the application quits, the same attribute is logged and then deleted. For an excellent article that provides an overview of application life-cycle events, please see Servlet App Event Listeners by Stephanie Fesler (04/12/2001, http://www.onjava.com/pub/a/onjava/2001/04/12/listeners.html). The four interfaces that you can expect to see on the exam are these:

When a servlet is initialized or destroyed:

javax.servlet.ServletContextListener.

contextDestroyed(ServletContextEvent sce) Notification that the
servlet context is about to be shut down.

contextInitialized(ServletContextEvent sce) Notification that
the Web application is ready to process requests.

When a context attribute is added, removed, or replaced:

javax.servlet.ServletContextAttributeListener.

attributeAdded(ServletContextAttributeEvent scab) Notification
that a new attribute was added to the servlet context.

attributeRemoved(ServletContextAttributeEvent scab) Notification
that an existing attribute has been removed from the servlet context.

attributeReplaced(ServletContextAttributeEvent scab) Notification
that an attribute on the servlet context has been replaced.

When a session is initialized or destroyed:

javax.servlet.http.HttpSessionListener.

sessionCreated(HttpSessionEvent se) Notification that a session
was created.

sessionDestroyed(HttpSessionEvent se) Notification that a session
became invalid or timed out.

When a session attribute is added, removed, or replaced:

HttpSessionAttributeListener.

attributeAdded(HttpSessionBindingEvent se) Notification that
an attribute has been added to a session.

attributeRemoved(HttpSessionBindingEvent se) Notification that
an attribute has been removed from a session.

attributeReplaced(HttpSessionBindingEvent se) Notification that
an attribute has been replaced in a session.

Context Within a Distributable Web Application

3.3 Distinguish the behavior of the following in a distributable:

Servlet context init. parameters.

Servlet context listener.

Servlet context attribute listener.

Session attribute listeners.

The behavior of these listeners in a distributable is exactly the same as those discussed in the previous section, with one notable exception: Event notification of addition, removal, or replacement will affect the listener for only that context. No other context, such as other JVMs on the same or other machine, will know about the listener events.

Chapter Summary

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. A PUT is for uploading a file. There are events associated with each type of request, such as clicking a hyperlink sending a GET request, but clicking a form button sends a POST 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. Going the other way, the container wraps the response parameters with the HttpServletResponse object which is passed back to the container.

Containers have the idea of 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. The container also manages the servlet life-cycle by initializing a servlet with a call to the init() method, a call to the service() method upon every request, and by calling a servlet's destroy() method just prior to removing it from memory. The container also allows you to monitor context and session events with listeners that are event-driven triggers. When an attribute changes, special targeted methods are called. In them, you can define special actions such as "add a note to the log every time the user count changes."

Lastly, the servlet specifies a RequestDispatcher object which performs servlet forwarding. Notice that this is different from redirection, where the servlet would return a new URL to the browser that triggers the browser to try to get that page. The RequestDispatcher doesn't redirect; rather it "dispatches" or performs forwarding.

KEY TERMS

Redirection

Servlet Life-Cycle

Servlet Forwarding and Includes

Servlet attribute

Context parameters

Application session

listeners

Apply Your Knowledge

Review Questions

What methods of the Servlet interface are invoked at different points in the servlet life cycle?

What HTTP methods are supported by HttpServlet?

What objects are passed to the servlet's service() method?

What is a distributable application?

Why is it a bad idea to synchronize a servlet's service() method?

What is the relationship between an application's ServletConfig object and ServletContext object?

What mechanisms are used by a Servlet Container to maintain session information?

What are the four events that are defined in the Servlet API?

How are request dispatchers used?

Exam Questions

Which of the following methods are defined in the Servlet interface?

init()

service()

finalize()

destroy()

Which of the following objects are passed to a servlet's service() method?

ServletRequest

HttpServletRequest

ServletResponse

HttpServletResponse

By default, how many instances of a servlet are created by a Servlet Container?

One

One per request

One per session

None of the above

Which of the following exceptions are defined by the Servlet API?

ServletException

InitializationException

UnavailableException

ServletContextException

Which of the following are used by Servlet Containers to maintain session information?

cookies

hidden form fields

HTTPS protocol information

URL rewriting

Which of the following event listeners are defined by the Servlet API?

HttpSessionBindingListener

HttpSessionEventListener

HttpSessionParameterListener

HttpSessionAttributeListener

Which of the following methods are defined by the RequestDispatcher interface?

dispatch()

include()

redirect()

forward()

Which of the following is the name of the cookie used by Servlet Containers to maintain session information?

SESSIONID

SERVLETID

JSESSIONID

CONTAINERID

Answers to Review Questions

The init() method is invoked during the initialization phase.
The service() method is invoked during the request processing (service)
phase. In other words, init() is invoked the first time the servlet
runs, but service() is invoked once for every request the servlet
receives. The destroy() method is invoked when the servlet is to
be taken out of service. Refer to the section, "Servlet
Life-cycle."

A distributable application is an application that is distributed over
multiple JVMs. Refer to the In the Field, "How Does
a Servlet Work?"

When the synchronized keyword is used with a servlet's service()
method, requests to that servlet are handled one at a time in a serialized
manner. This means that the processing capabilities of the Servlet Container
are minimized. Refer to the section, "Servlet
Life-cycle."

An application's ServletConfig object contains its ServletContext
object and provides access to this object via its getServletContext()
method. Refer to the section, "Web Application
Context."

Cookies, URL rewriting, and HTTPS protocol information are used to maintain
session information. Refer to the section, "Session."

The four events that are defined by the Servlet API are HttpSessionEvent,
HttpSessionBindingEvent, ServletContextEvent, and ServletContextAttributeEvent.
Refer to the section, "Servlet Life-cycle."

Request dispatchers are used to forward requests to other servlets or to
include the results of other servlets. Refer to the section, "Using
a RequestDispatcher."

Answers to Exam Questions

C. The finalize() method is not defined by the Servlet
interface. Refer to the section, "Servlet Life-cycle."

A, C. ServletRequest and ServletResponse methods are
passed to the service() method. Refer to the section, "Servlet
Life-cycle."

A. By default, only one instance of a servlet is created by a Servlet Container.
Refer to the section, "Servlet Life-cycle."