http://www.developer.com/

Back to article

Understanding Servlets


April 8, 2003


This is Chapter 21: Servlets from the book Java 2 Primer Plus (ISBN: 0-672-32415-6), written by Steven Haines and Steven Potts, published by Sams Publishing.

© Copyright Sams Publishing. All rights reserved.


Chapter 21: Servlets

You will learn about the following in this chapter:

  • What servlets are why you need them

  • How servlets work

  • How to set up a Jakarta Web server to run servlets

  • How to program servlets in Java

  • How to call other Java classes from inside servlets

  • How to maintain the state of a servlet using cookies in the user's browser

  • How to maintain the state of a servlet using a session on the server

When Java 1.01 was released, it was heavily oriented toward the development of applications that can run in a browser. The Applet architecture had received a lot of consideration and most of that release supported the GUI classes that facilitated their creation. Almost immediately, the question was asked, "What about developing for the server?"

The Java language offers much more to the developer than cool Internet graphics. It is a robust, highly object-oriented language that is easy to learn. It has a small footprint, and it can run on almost any computer that you can name. It is supported by a host of standard extensions that enables you to perform tasks, such as managing sound and video, without making you learn a host of proprietary command sets and scripting languages. It was only natural for Java to become popular on the server as well.

Java's presence on the server side was initially through programs called servlets. Servlets, like applets, are intended to run in a container. The servlet's engine is not called a browser, however, but a servlet container. Both applets and servlets have to be written to a pretty exact specification, but the servlets cannot have graphical user interfaces. They can, however, extract data from HTML forms, and they can create HTML and send it to the client to provide visual feedback.

With the introduction of the Java 2 Enterprise Edition (J2EE), servlets became only one of many server-side technologies available to programmers. Enterprise JavaBeans (EJB) have become popular for complex applications, but servlets remain as popular as ever.

In this chapter, we are going to cover servlets from the developer's standpoint. First, you will learn how to obtain and install a servlet container on your machine. Next, you will learn how to develop, deploy, and run servlets. Following that, you will learn how to write servlets that maintain user information across transactions.

What Servlets Are and Are Not

Servlets are miniature programs that must be run inside another program called a container. The container is responsible for brokering communication between the servlet and the outside world. Beyond that, servlets are like every Java application. They can import packages, write to the hard drive, and even install viruses on your machine. By default, servlets are trusted code. The reason is that if someone has enough permission on your computer to install a servlet, he already has enough power to tie the whole machine in knots anyway. The thought is that this installer is a trusted person, so the work that he does should be trusted, too.

Servlets are not Java applications. They must be run inside a container instead of from a command line. That being said, you can add almost any functionality available to a Java application to a servlet also.

Servlets are not the only way for the server to communicate with a browser. A Web server is an HTTP application. It receives communication via the HTTP protocol and it communicates with the browser via HTTP also. You can write your own HTTP server-side application that processes its own requests, bypassing both servlets and the servlet container. This chapter contains a simple example of how that is done.

Why Do I Need Servlets?

Servlets are here to make your life easier. If the only option available was to write HTTP applications from scratch every time new functionality was needed, not much development would take place on the Web. Not many organizations could afford to write HTTP programs from scratch. The existence of the servlet container avoids the cost of having to include the entire HTTP header processing code in every program. Servlets extend classes that take care of all that work behind the scenes.

Another advantage of servlets is that they scale nicely. The servlet container is responsible for instantiating your servlet whenever it is needed. If it is needed a lot, the servlet container has the option of creating as many threads or instances of your servlet as its load-balancing algorithms indicates it needs.

Servlets make good use of machine resources. They run in threads that are created by the servlet container. Each individual HTTP application program runs in its own process. Processes are far more expensive to create than threads, so the servlet approach is more efficient. Servlet containers can also pool connections so that the threads already created are reused instead of discarded. The ancestor of the servlet, the CGI program, lacked these features and has faded in popularity as a result.

How Servlets Work

Servlets are really parts of an application and require a servlet container to run. This servlet container is responsible for instantiating your servlet and calling the appropriate methods in the servlet at the appropriate times.

When you type the name of a servlet, you are really making a call to a program that is located on a server and not on your machine. At first, this process seems like magic, but after a little study you will see that this process only requires that each piece of software in the process perform a fairly simple set of tasks. Figure 21.1 shows this process graphically.

Figure 21.1.

The servlet container is responsible for instantiating your servlets.

  1. You type in the URL of a servlet that you want to call.

  2. The browser creates a request that contains the servlet and the name of your machine so that the server will know who to send feedback to.

  3. The server receives the request and hands it to the servlet container. The servlet container is a program that knows how to run servlets.

  4. The servlet container checks to see if any instances of this servlet are already in memory. If not, it loads an instance and runs the servlet's init() method.

  5. The servlet container waits for the init() method to finish. It then calls the service() method in your servlet from a new thread.

  6. The service() method calls the doGet() or doPost() method depending on what the request type is.

  7. A second user's browser requests that the same servlet be run on its behalf.

  8. The servlet container notices that an instance of the servlet is already in memory. So, it creates a new thread and starts running the same servlet that you are running.

  9. This new thread calls the service() method.

  10. If this is an HTTP servlet, the service() method calls the doGet() or doPost() methods.

  11. The first thread finishes and a response is sent to the Web server, which forwards it to your browser.

  12. The second thread finishes and a response is sent to the Web server, which forwards it to the second user's browser.

  13. At a certain point in the future, the servlet container decides to deinstantiate the servlet. At that point it calls the destroy() method once for each instance in memory.


Caution - Whether more than one instance of a single servlet is in memory depends on whether it is declared to be thread-safe. A servlet is assumed to be thread-safe unless it implements the SingleThreadModel interface. If it implements this interface, a new instance will be created for each simultaneous access. This has serious performance penalties associated with it, so it should only be done if absolutely necessary.


Setting Up a Web Environment

Before you can develop and test servlets, you need to set up a Web development environment. You will need several pieces of software to accomplish this. The first one is a recent version of Java, which you probably already have installed on your machine. In case you don't, however, you can obtain the Java Software Development Kit (SDK) from Sun Microsystems at http://www.java.sun.com.

You most likely have a browser installed on your machine also. You will want to make sure that you have an up-to-date browser version, so it would be a good idea to check this version against the latest release that is available on the Microsoft and Netscape Web sites. There are times when the two leading browsers behave differently, so it is also a good idea to install both of them on your machine for testing.

In addition, you need some way to compose and edit programs. All the examples in this chapter can be typed in using Notepad or vi and run from a command line.


Note - Java-specific editors are available, and you might find that it is worth your while to learn how to use one. Forte has a version that is available for free at http://www.java.sun.com. JBuilder and Visual Café are two commercial products that are popular with developers also.


The third piece of the servlet puzzle is the servlet container itself. If you are currently running a Web server that provides servlet support, you can skip this step. If you don't have a servlet container running already, you will need to follow the instructions in the next section to set up the Tomcat server on your machine. Tomcat contains a light version of a Web server that is complete with a servlet container.

Installing Jakarta Tomcat

Jakarta Tomcat is available at no cost from the Apache Web site at http://www.apache.org/.

The link for Tomcat 4.0.4 is

http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.4/bin/.

Choose a release that is right for your needs. If you are running Java 1.4, the following self-extracting .exe file will be correct for you:

jakarta-tomcat-4.0.4-LE-jdk14.exe

Caution - As new versions of Tomcat are released, the links that lead to them will differ from those shown previously. In these cases, you will need to go to the http://jakarta.apache.org/ Web site and navigate to the newest release.


You will then be prompted to enter the location where you want this .exe file stored. Next, open Windows Explorer and double-click the name of the .exe file. This will open an installation wizard that will guide you through the installation. After you answer a few questions, you will be told that the installation is complete.

If you are running under Unix, you can download the tar version and follow the instructions on the Apache Web site on how to install Tomcat on your machine.


Caution - Vendor Web sites change from time to time. If the previous steps don't work exactly, look for similar links at each step, and you should be able to succeed in getting Tomcat installed.


Starting Tomcat

You start Tomcat by opening a command window and typing the following command.

java -jar -Duser.dir="C:\Program Files\Apache Tomcat 4.0" 
"C:\Program Files\Apache Tomcat 4.0\bin\bootstrap.jar" start

Tomcat will output several lines of responses like these, which provide feedback that the server is really running.

Starting service Tomcat-Standalone
Apache Tomcat/4.0.4
Starting service Tomcat-Apache
Apache Tomcat/4.0.4

On some operating systems, the installation script places some shortcuts in your file system to make the task of starting Tomcat easier. On our test machine, Windows XP, these shortcuts were placed in a directory called:

C:\Documents and Settings\Your Name\Start Menu\Programs\
   Apache Tomcat 4.0

Your Name will be replaced by the login name of the machine that you are using.

Another link on that page opens a browser that contains the root page for the copy of the Tomcat documentation that is stored on your local hard drive. Figure 21.2 shows this page.

Figure 21.2

The Tomcat documentation provides detailed instructions about how to get the server and keep it running.


Note - You can find answers to many of your questions with these pages, so it would be a good idea to bookmark the root page in your browser.


Most of the work that you will do with Tomcat will involve four of the directories located under the root Tomcat directory. These directories are

  • C:\Program Files\Apache Tomcat 4.0\bin—This directory contains scripts to perform functions such as startup, shutdown, and so on. Under Windows, these scripts are .bat files, and under Unix, they are .sh files.

  • C:\Program Files\Apache Tomcat 4.0\conf—This directory contains configuration files, which control the behavior of the server. Most of these files are in XML format. The most important file in here is called server.xml, the main configuration file for the server.

  • C:\Program Files\Apache Tomcat 4.0\logs—This directory contains the logs that are created by the Tomcat server. You inspect these logs to discover clues about why certain problems are occurring with the installation and/or your programs.

  • C:\Program Files\Apache Tomcat 4.0\webapps—This directory is where you put your programs. Web servers don't like to access files all over your computer because of the security risks. They prefer to allow clients to access only files that are stored in one place and its subdirectories.

Testing the Installation

After you have finished the installation, you will want to test the server using servlets provided by Apache before writing your own. The reason for this is that any problem you have running their servlets is certainly a configuration problem. If you run your own servlets without first verifying that the installation is correct, the problem could be either in the installation or with your servlet.

Testing the installation is easy. First, start Tomcat by following the procedure described previously. Next, type the following command in a browser address box:

http://localhost:8080

You should immediately see a screen that looks like Figure 21.3.

Figure 21.3

The Tomcat localhost home page will display when the server is running properly.

If you do not see this page immediately, the most likely reason is that you have another program listening to port 8080. In that case, edit the file called server.xml in the C:\Program Files\Apache Tomcat 4.0\conf directory. Look for the following lines:

  <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
<Connector 
    className="org.apache.catalina.connector.http.HttpConnector"
        port="8080" minProcessors="5" maxProcessors="75"
        enableLookups="true" redirectPort="8443"
        acceptCount="10" debug="0" connectionTimeout="60000"/>

Edit the fourth line and change it to some value more than 1024, like 1776. It will look like this:

  <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
  <Connector className=
       "org.apache.catalina.connector.http.HttpConnector"
        port="1776" minProcessors="5" maxProcessors="75"
        enableLookups="true" redirectPort="8443"
        acceptCount="10" debug="0" connectionTimeout="60000"/>

Save this file and restart the Tomcat server. Repeat the test by opening a browser, but this time type

http://localhost:1776

If this doesn't open the magic Web page shown in Figure 21.3, consult the troubleshooting documentation that Tomcat installed on your hard drive.


Note - This chapter uses port 1776 for all the examples. The reason for this is that port 8080, the default Tomcat port, was already in use on our test machine.


Programming Servlets

Servlet programming is built on a solid foundation of prewritten Java classes. Instead of creating servlets as Java classes that are started by calling a main method, servlets are extensions of other classes that already know how to interact with Web servers and servlet containers.

The following classes and interfaces are the most important ones to understand when programming servlets:

  • Servlet—This interface defines the init(), service(), and destroy() methods. It also defines two more methods that implementing classes must provide, getServletConfig() and getServletInfo(), which allow you to query the servlet for information about the servlet itself (author, version, copyright, and so on). The servlet container is programmed to expect a servlet to implement these five methods. This is how code that you write can be plugged into a framework such as the servlet container so easily. Advanced programmers might want to implement this interface directly in a new class instead of using either the GenericServlet class or HttpServlet class. This would require you to write quite a bit of code, however, and it is not needed to satisfy ordinary requirements.

  • GenericServlet—The GenericServlet class provides a simple implementation of the Servlet interface. It is called "Generic" because it does not assume that the protocol it will process will be HTTP. If you were writing your own protocol, you would extend this class. Normally, you override the service() method.

  • HttpServlet—This is the class that is most often extended when servlets are written. It extends GenericServlet to provide HTTP-specific processing. Because HTTP is so common, servlets that extend this class tend to be the easiest to write. Normally, you override the doGet(), doPost(), or both methods of this class. This class contains a default implementation of service() that calls the appropriate doXXX() method, depending on the type of request that is received.

  • ServletRequest—This interface defines an object that contains the information that the client has provided, along with his request to run the servlet. A concrete implementation of this object is ServletRequestWrapper class.

  • HttpServletRequestWrapper—This is an extension of the ServletRequestWrapper that contains information specifically assuming that the request will be in HTTP format. In most servlets, this class is accessed polymorphically via a handle to the ServletRequest interface. See Chapter 7, "Inheritance," for information on how this works.

  • ServletResponse—This interface defines a convenient way for a servlet to communicate the information that it wants to send to the client to the servlet container. A concrete implementation of this object is ServletResponseWrapper class.

  • HttpServletResponseWrapper—This is an extension of the ServletResponseWrapper that assumes that the response will be in HTTP format. In most servlets, this class is accessed polymorphically via a handle to the ServletResponse interface.

Programming Generic Servlets

Even though most of this chapter will deal with HTTP-based servlets, it is useful to understand how a servlet can be created that is not tied to this protocol. Listing 21.1 shows a simple generic servlet.

Listing 21.1 The GenericHello Class

/*
 * GenericHello.java
 *
 * Created on June 21, 2002, 5:28 PM
 */


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

/**
 *
 * @author Stephen Potts
 * @version
 */
public class GenericHello extends GenericServlet
{
  
  /** Initializes the servlet.
   */
  public void init(ServletConfig config) throws ServletException
  {
    super.init(config); 
    
  }
  
  /** Destroys the servlet.
   */
  public void destroy()
  {
    
  }
  
  public void service(ServletRequest req, ServletResponse resp)
  throws ServletException, java.io.IOException
  {
    resp.setContentType("text/html");
    java.io.PrintWriter out = resp.getWriter();
    out.println("Hello from the GenericHello Servlet");
    out.close();
  }
  
  /** Returns a short description of the servlet.
   */
  public String getServletInfo()
  {
    return "This servlet tests the GenericServlet class";
  }
  
}

Notice that this class extends the GenericServlet class. As discussed previously, this is a protocol-neutral servlet class.

public class GenericHello extends GenericServlet

The init() method is overridden here. Notice that it is passed a ServletConfig class, which it passes along to the super(GenericServlet) class's init() method. The ServletConfig class contains references to the servlet name and the ServletContext object. For now, we can ignore these objects.

  public void init(ServletConfig config) throws ServletException
  {
    super.init(config);
  }

We override the destroy() method just for show.

  public void destroy()
  {
    
  }

We also override the getServletInfo() method so that you will have an example of how this is done.

  public String getServletInfo()
  {
    return "This servlet tests the GenericServlet class";
  }

Finally, the service() routine is where the action is, what little there is in this example.

  public void service(ServletRequest req, ServletResponse resp)
  throws ServletException, java.io.IOException
  {
    java.io.PrintWriter out = resp.getWriter();
    out.println("Hello from the GenericHello Servlet");
    out.close();
  }

We create a handle to the response object's PrintWriter object so that we can send some information to the client. We are not interested in any of the information available from the client in this simple example. We print a string to this object, and then close it. The servlet container is responsible for actually getting the string to the client.

Deploying the Servlet

Under JDK 1.4, all the classes needed to compile this program are automatically installed. This makes it simple to compile the program. You just type the following at a command line:

javac GenericHello.java

The servlet is now compiled into a .class file in this same directory. If this were a garden-variety Java application, we could run it by typing the following:

java GenericHello
Exception in thread "main" java.lang.NoSuchMethodError: main

Being a servlet, this class has no main() method, and the Java runtime engine points that out to you by throwing an exception.

We could just go and type the name of this servlet in the address line of our browser, but that will give us an error message stating that the servlet container doesn't know anything about this servlet as shown in Figure 21.4.

Figure 21.4.

The Tomcat server doesn't know anything about this servlet, so it provides a polite error message.

We have a servlet container running, and we have a servlet that compiles. What we need is a way to tell the servlet container about this servlet. A good quick-hitter approach to this is to place the servlet in the ...\webapps\examples\WEB-INF\classes directory. After that is done, we can type the following URL in your browser's address field (with Tomcat running):

http://localhost:1776/examples/servlet/GenericHello

If you installed Tomcat using the default port of 8080, you would substitute "8080" for the "1776."

The examples string indicates that the GenericHello class is a servlet, and that its class file can be found under the examples subdirectory. Figure 21.5 shows the result of running GenericHello.

Figure 21.5.

The GenericServlet's output contains no formatting information.

Notice that the message is output to the screen in whatever font the browser chooses. This is done because we provided no input to the browser on how to format the results. This desire to have more control over the layout is the motivation for creating the HTTPServlet class.

Next, let's modify our example to use the HTTPServlet class so that we can have more control over the output. Listing 21.2 shows the code for the new servlet.

Listing 21.2 The HTTPHello Example

/*
 * HTTPHello.java
 *
 * Created on June 21, 2002, 9:59 AM
 */

import javax.servlet.*;
import javax.servlet.http.*;

/**
 *
 * @author Stephen Potts
 * @version
 */
public class HTTPHello extends HttpServlet
{
  
  /** Initializes the servlet.
   */
  public void init(ServletConfig config) throws ServletException
  {
    super.init(config); 
    
  }
  
  /** Destroys the servlet.
   */
  public void destroy()
  {
    
  }
  
  /** Processes requests for both HTTP <code>GET</code>
   * and <code>POST</code> methods.
   * @param request servlet request
   * @param response servlet response
   */
  protected void processRequest(HttpServletRequest request, 
                  HttpServletResponse response)
  throws ServletException, java.io.IOException {
    response.setContentType("text/html");
    java.io.PrintWriter out = response.getWriter();
    out.println("<html>");
    out.println("<head>");
    out.println("<title>HTTPHello</title>");
    out.println("</head>");
    out.println("<body>");
    
    //Make the font large
    out.println("<H1>");
    //Make the font bold
    out.println("<B>");
    
    out.println("Hello from the HTTPHello Servlet");
    out.println("</H1>");
    out.println("</B>");
     
    out.println("</body>");
    out.println("</html>");
    out.close();
  }
  
  /** Handles the HTTP <code>GET</code> method.
   * @param request servlet request
   * @param response servlet response
   */
  protected void doGet(HttpServletRequest request,
            HttpServletResponse response)
  throws ServletException, java.io.IOException {
    processRequest(request, response); 
  }
  
  /** Handles the HTTP <code>POST</code> method.
   * @param request servlet request
   * @param response servlet response
   */
  protected void doPost(HttpServletRequest request,
            HttpServletResponse response)
  throws ServletException, java.io.IOException {
    processRequest(request, response);
  }
  
  /** Returns a short description of the servlet.
   */
  public String getServletInfo() {
    return "This is the HTTPHello Servlet";
  }
  
}

This servlet was created using the Forte for Java code editor, which generates an empty HTTPServlet for you. This can save you time when writing servlets, but it can retard learning. Until you become familiar with the purpose of every line of code in this example, any tools will hamper learning. After you can write servlets in your sleep, the tools will speed up your coding a little.

Notice that we now have an extra import statement. This package will give us HTTP processing.

import javax.servlet.http.*;

This servlet extends HTTPServlet. This will impact us because we will be overriding doGet() and doPost() instead of service().

public class HTTPHello extends HttpServlet

We have overridden the doGet() and doPost() methods in a unique fashion.

  protected void doGet(HttpServletRequest request,
                 HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
    processRequest(request, response);
  }

  protected void doPost(HttpServletRequest request,
                 HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
    processRequest(request, response);
  }

In both cases we simply made a call to a method that we named processRequest() and passed the request and response objects to it. There is nothing special about the name processRequest(). We could have called it xyz(). Later in this chapter we will look at the HTTP protocol and the difference between the Get and Post commands.

The real work in our example is now done in the processRequest() method. This method is passed in both an HttpServletRequest object and an HTTPServletResponse object.

  protected void processRequest(HttpServletRequest request,
                     HttpServletResponse response)
  throws ServletException, java.io.IOException {

These will be used extensively in future examples, but for now, we only use the response object.

    response.setContentType("text/html");
    java.io.PrintWriter out = response.getWriter();

We use the PrintWriter object to put data into the response object for transmission back to the client. Notice that HTML code makes up the contents of the string.

    out.println("<html>");
    out.println("<head>");
    out.println("<title>HTTPHello</title>");
    out.println("</head>");
    out.println("<body>");
    

We add this line to make the font large.

    out.println("<H1>");

This line makes the font bold.

    out.println("<B>");

This line contains the contents of what we want displayed.

    out.println("Hello from the HTTPHello Servlet");

The result of running this is similar to when we ran the GenericHello servlet, as shown here in Figure 21.6.

Figure 21.6

The HTTPServlet enables us to format our output by using HTML commands.

Understanding HTTP

Because you will be using HttpServlet class to implement most of the servlets that you will ever write, it is important for you to understand what HTTP is. HTTP stands for Hypertext Transfer Protocol. A protocol is simply a published agreement between clients and servers that specifies what data, and its syntax, will be passed from one party to the other.

HTTP is an application layer protocol, which means that it depends on lower-layer protocols to do much of the work. In the case of HTTP, this lower-layer protocol is TCP/IP. The information in HTTP is transferred as plain ASCII characters. Plain text is convenient for programmers because the instructions are human-readable. By contrast, binary protocols like those used in RMI and CORBA are much more difficult to decipher when searching for the cause of a programming error.

HTTP is a stateless and connectionless protocol. Stateless means that each request and response pair constitutes an entire conversation. There is no memory of one transaction available to the next transaction. It is kind of like computerized amnesia. Connectionless means that there is no concept of a logon or logoff in HTTP, as there is in FTP. In fact, the requester is anonymous from the protocol's point of view.

Being stateless is both good and bad. It is good from a performance standpoint because there is no need for the program that accepts HTTP requests (the Web server) to remember any state information. This greatly reduces the server's workload and makes it possible for one server to process thousands of clients. On the other hand, being stateless limits the usefulness of the protocol. If you want to create an application that does some work, asks the user some questions, then does some more work, you have to manage this in the code that you write. We will cover this problem of saving state later in the chapter.

A connectionless protocol also has positives and negatives. If no time is spent establishing a connection, the server can service more requests per unit of time. This also limits the usefulness of the protocol. If you want a user to logon, do some stuff, then logoff, you will have to write your own code to do that. Fortunately, the servlet classes support this requirement pretty well.

HTTP is a request and response protocol. This means that it is composed of pairs of requests and responses, as shown in Figure 21.7.

Figure 21.7.

The HTTP protocol is based on the assumption that every request will be answered with one response.

The format of the request is all done in plain text and is sent as a string from the client to the server. The server reads the message and performs the task that it has been instructed to do. In some cases, this task is to retrieve a static document and send it back to the client's browser for display. In other cases, this request is for a servlet to be run and the results of that, if any, to be sent to the client.

The GET Command

The most frequently used HTTP command is the GET command. This command states that the browser is to ask the server to send back a copy of a document. If that document has already been cached, the browser might use that one instead of retrieving it again. Listing 21.3 shows a simple HTTP GET request for a document.

Listing 21.3 A Request for xyz.html

GET /xyz.html HTTP/1.0
User-Agent: Mozilla/4.51  (WinNT; I)
Accept: image/gif, image/jpeg, image/pjpeg, */*
  • The GET means that we want to retrieve a result. Also those parameters, if any, will be appended to the name of the document or servlet.

  • The User-Agent tag tells the server what version of the browser the client is running. This gives the server a chance to tailor the response to suit this browser.

  • The Accept tag tells the server what kind of replies, in addition to text, the browser can process.

The job of the Web server is to parse this text and decide how to handle the results. If you want to pass parameters to the server, you can do that by appending them to the name of the document, as shown in Listing 21.4.

Listing 21.4 Passing Parameters with GET

GET /xyz.html?myparm=hello&myotherparm=world HTTP/1.0
User-Agent: Mozilla/4.51  (WinNT; I)
Accept: image/gif, image/jpeg, image/pjpeg, */*

In this listing, we are telling the server to return that HTML page modified by the values in the parameters. The special syntax using the ? tells the server that parameters start here. A parameter/value pair is indicated by the =. The & indicates that another parameter follows this. Notice that there are no quotes around the strings. If numbers are placed on the line, they are sent as strings also, and it is up to the server or servlet to do any conversion or casting to another data type.

The parameters modify the behavior of the document or servlet. The nature of the modification is a decision of the page designer or servlet programmer. The names of the parameters are important because they will be used to extract the value for this parameter from the request object in the servlet.

There is a limit of 255 characters that can be used to pass parameters appended in this way. The reason for this is that some Web servers store this string in an environment variable that is rather small. If you use a length greater than 255, it may or may not work, depending on the client. In practice, if there is a parameter list that long, the programmer will use the POST command instead.

Another drawback of passing the parameters this way is that they appear in the address bar of the browser. If your password is one of the data items, this could be a problem because the history kept by your browser now contains your password in plain text.

Calling a servlet is very similar. Listing 21.5 contains the HTTP message to invoke a servlet:

Listing 21.5 Calling a Servlet

GET /xyz.html?myparm=hello&myotherparm=world HTTP/1.0
User-Agent: Mozilla/4.51  (WinNT; I)
Accept: image/gif, image/jpeg, image/pjpeg, */*

Notice that we don't specify the name of the server in this command. This is because a socket to this machine has already been opened before this message is sent. Notice also that there is no special syntax to indicate that this is a servlet. It is the responsibility of the Web server to figure out what kind of request it has been given.

The POST Command

The POST command is used to send data to the Web server. By convention, POST requests are not answered out of cache, but rather sent to the server every time. Listing 21.6 contains an example of a post command.

Listing 21.6 The POST Command

POST /xyz.html HTTP/1.0
User-Agent: Mozilla/4.51  (WinNT; I)
Accept: image/gif, image/jpeg, image/pjpeg, */*
Content-Length: 34
Content-Type:application/x-www-form-urlencoded

myparm=hello&myotherparm=world

Notice that there is a blank line between the header and the contents of the message; this is required. The length must also be passed as well as a content type. There is no stated limit to the length of the parameters to be passed using the POST command. In addition, the values of the parameters are not displayed on the command line of the browser. Aside from these differences, the behavior of the GET and the POST commands are identical.

The Other Commands

The HEAD command is like a GET command that returns only the header, but not the contents of the response. This can be useful if the browser wants only information about the document, but it doesn't have much practical value for servlet development. Other commands such as PUT, DELETE, LINK, and UNLINK are in the specification, but because they have little or no value to the servlet developer, we will not cover them here.

HTTP 1.1

A new version, HTTP 1.1, has been proposed and published by the Internet Engineering Task Group (IETF). This new version will add quite a few improvements to the HTTP 1.0 standard, but none that directly impact servlet developers. One improvement that indirectly impacts developers is the fact that connections are now kept alive by default. This means that the server will discontinue its conversation with the client, but without actually closing the connection. This connection can be reused, but it is not associated with the client that used it last. This behavior changes the performance, but not the syntax, of the HTTP commands.

Programming HTTP

The browser is a program that processes HTTP commands, among other things. The Web server is also an HTTP processing program. Both of these programs fill a place in our programming world, but they are not the only ways to process HTTP commands.

You can write a fairly simple pair of Java programs that communicate with each other, with browsers, and with servers using HTTP. Understanding how they work will clarify many points that are sometimes fuzzy when dealing with browsers and Web servers. Listing 21.7 shows a simple Java program that is able to talk to the Tomcat server using port 1776.

Listing 21.7 The HTTPFetch Class

/*
 * HTTPFetch.java
 *
 * Created on June 18, 2002, 2:54 PM
 */


import java.io.*;
import java.net.*;

/**
 *
 * @author Stephen Potts
 * @version
 */
public class HTTPFetch
{
  
  /** Creates new HTTPFetch */
  public HTTPFetch()
  {
  }
  
  public static void main (String[] args)
  {
   try
   {
     URL url = new URL(
     "http://localhost:1776");
     BufferedReader in = new BufferedReader(
           new InputStreamReader(url.openStream()));
     String line;
     while ((line = in.readLine()) != null)
     {
      System.out.println(line);
     }
     in.close();
   }catch(Exception e)
   {
     e.printStackTrace();
   }
  }
}

This program simply initiates communication with the Tomcat server and receives the default home page. This is the page that was shown in Figure 21.3.

This program makes heavy use of the HTTP processing built into Java. We first declare a new URL object and pass in the address of the Tomcat server as a parameter to the constructor.

     URL url = new URL(
     "http://localhost:1776");

Next, we open the URL's inputStream in a Buffered reader.

     BufferedReader in = new BufferedReader(
           new InputStreamReader(url.openStream()));
     String line;

Finally, we look through it and write each line to the screen.

     while ((line = in.readLine()) != null)
     {
      System.out.println(line);
  }

To run this program, you type the following at the command line, not in a browser:

  java HTTPFetch

Instead of displaying this page in a nice graphical format, as a browser would, this program just writes the code to standard output as shown here.

<!doctype html public "-//w3c//dtd html 4.0 transitional//en"
 "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
  <head>
  <meta http-equiv="Content-Type" content="text/html;
        charset=iso-8859-1">
  <title>Jakarta Project - Tomcat</title>
  <style type="text/css">
   <!--
    body {
      color: #000000;
      background-color: #FFFFFF;
      font-family: Arial, "Times New Roman", Times;
      font-size: 16px;
    }
 
    A:link {
      color: blue
    }
 
    A:visited {
      color: blue
    }
 
    td {
      color: #000000;
      font-family: Arial, "Times New Roman", Times;
      font-size: 16px;
    }
 
    .code {
      color: #000000;
      font-family: "Courier New", Courier;
      font-size: 16px;
    }
   -->
  </style>
</head>
 
<body>
 
<!-- Header -->
<table width="100%">
  <tr>
    <td align="left" width="130"><a href=
"http://jakarta.apache.org/tomcat/index.html"><img src=
"tomcat.gif" height="92" width="130" border="0" alt=
"The Mighty Tomcat - MEOW!"></td>
.
.
. 

Because of its length, only the first part of the output is displayed here, and that part is formatted to fit on this page. This program is similar to a browser's view source command.

The second part of this example is the HTTPServer program shown here in Listing 21.8.

Listing 21.8 The HTTPServer Class

/*
 * HTTPServer.java
 *
 * Created on June 18, 2002, 3:07 PM
 */


import java.io.*;
import java.net.*;

/**
 *
 * @author Stephen Potts
 * @version
 */
public class HTTPServer
{
  
  /** Creates new HTTPServer */
  public HTTPServer()
  {
  }
  
  public static void main(String[] args)
  {
   try
   {
     ServerSocket sSocket = new ServerSocket(1777);
     System.out.println("Created the socket");
     
     while (true)
     {
      System.out.println("Waiting for a client...");
      Socket newSocket = sSocket.accept();
      System.out.println("accepted the socket");
      
      OutputStream os = newSocket.getOutputStream();
      BufferedReader br = new BufferedReader(
      new InputStreamReader(newSocket.getInputStream()));
      
      String inLine = null;
      while (((inLine = br.readLine()) != null)
      && (!(inLine.equals(""))))
      {
        System.out.println(inLine);
      }
      System.out.println("");
      
      StringBuffer sb = new StringBuffer();
      sb.append("<html>\n");
      sb.append("<head>\n");
      sb.append("<title>Java Primer Plus\n");
      sb.append("</title>\n");
      sb.append("</head>\n");
      sb.append("<body>\n");
      sb.append("<H1>HTTPServer Works!</H1>\n");
      sb.append("</body>\n");
      sb.append("</html>\n");
      
      String string = sb.toString();
      
      //Put the output into a byte array
      byte[] byteArray = string.getBytes();
      
      //add some header information
      os.write("HTTP/1.0 200 OK\n".getBytes());
      os.write(new String(
      "Content-Length: "+ byteArray.length + "\n").getBytes());
      os.write("Content-Type: text/html\n\n".getBytes());
      //add the output
      os.write(byteArray);
      os.flush();
      
      //close it up
      os.close();
      br.close();
      newSocket.close();
     }//while
     
   }catch(Exception e)
   {
     e.printStackTrace();
   }
   
  }//main
}//class

This program is another very simple TCP/IP sockets program. The first thing that we do is create the socket:

     ServerSocket sSocket = new ServerSocket(1777);
     System.out.println("Created the socket");

Notice that we used a different port number because we have Tomcat on 1776, and we don't want a conflict. We loop and wait for a communication from a client on port 1777.

     while (true)
     {
      System.out.println("Waiting for a client...");
      Socket newSocket = sSocket.accept();
      System.out.println("accepted the socket");

When we get a communication from that port, we will create a handle to the socket that the client has handed us, and call it newSocket. We will use it to send information back to the client.

      OutputStream os = newSocket.getOutputStream();

From this point on, the program acts like any other Java IO program. We get the InputStream from the client.

      BufferedReader br = new BufferedReader(
      new InputStreamReader(newSocket.getInputStream()));

We echo the information that the client sends us to standard output.

      String inLine = null;
      while (((inLine = br.readLine()) != null)
      && (!(inLine.equals(""))))
      {
        System.out.println(inLine);
      }
      System.out.println("");

We then create some HTML code and put it in a StringBuffer.

      StringBuffer sb = new StringBuffer();
      sb.append("<html>\n");
      sb.append("<head>\n");
      sb.append("<title>Java Primer Plus\n");
      sb.append("</title>\n");
      sb.append("</head>\n");
      sb.append("<body>\n");
      sb.append("<H1>HTTPServer Works!</H1>\n");
      sb.append("</body>\n");
      sb.append("</html>\n");

We transform it to a String object, and then to a byteArray so that the OutputStream can accept it.

      String string = sb.toString();
      
      //Put the output into a byte array
      byte[] byteArray = string.getBytes();

Next, we add the HTTP header information.

      os.write("HTTP/1.0 200 OK\n".getBytes());

We add the Content-Length.

      os.write(new String(
      "Content-Length: "+ byteArray.length + "\n").getBytes());

We add the Content-Type.

      os.write("Content-Type: text/html\n\n".getBytes());

Next, we add the HTML that we wrote earlier.

      os.write(byteArray);
      os.flush();

Finally, we close up shop.

      //close it up
      os.close();
      br.close();
      newSocket.close();

Run this server by typing the following:

java HTTPServer

It pauses at the Waiting for a client ... until a client tries to connect. Open a browser and type the following:

http://localhost:1777/

Note that a Web server doesn't need to be running for this to work. This program is its own server.

Created the socket
Waiting for a client...

Action by the browser causes this server to receive the following communication:

accepted the socket
GET / HTTP/1.1
Host: localhost:1777
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US;
            rv:0.9.4.1)
 Gecko/20020508 Netscape6/6.2.3
Accept: text/xml, application/xml, application/xhtml+xml,
 text/html;q=0.9, image/png, image/jpeg, image/gif;q=0.2,
 text/plain;q=0.8, text/css, */*;q=0.1
Accept-Language: en-us
Accept-Encoding: gzip, deflate, compress;q=0.9
Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66
Keep-Alive: 300
Connection: keep-alive

Waiting for a client...

You end this program by typing Ctrl-c.

We see that the browser issued a GET. We also see that the browser didn't stipulate which document to return. The server has to decide what to do in this case. Normally, commercial servers return index.html.

We see that the browser message is in HTTP 1.1. We also see that it was a Netscape 6.2.3 browser. We also see several more pieces of information that we could make use of if we were writing a fancy server. At the end, it loops back and waits for a client. The server responds to this request by stuffing the HTTP commands that we created into the OutputStream that the client sent to us. The result is displayed on the screen, as shown in Figure 21.8.

Figure 21.8

The HTTP protocol is sent to the browser that displays it.

We can see that the browser had no trouble receiving and understanding this communication. If we run the HTTPFetch command against the HTTPServer command, we can see the details of what the HTTPServer returned. All that we have to do is change the port number in the HTTPFetch program to 1777, and we are ready.

     URL url = new URL("http://localhost:1777");

Open a second command window and type

java HTTPFetch

The result will now be output to the screen.

<html>
<head>
<title>Java Primer Plus
</title>
</head>
<body>
<H1>HTTPServer Works!</H1>
</body>
</html>

Note - If you understand this section on HTTP, you will be in a great position to comprehend what is happening behind the scenes when your servlets are running.


HTML Forms and Servlets

Servlets that don't accept input from the client are of very little practical value outside of testing. Real-world servlets often receive data and additional instructions from clients in the form of parameters. The most common way for these parameters to be entered by the user is by using HTML forms.

Numerous HTML books are on the market, so I won't try to replace them here. You will, however, learn just enough HTML to be able to do data entry so that you can pass it to your servlets. Listing 21.9 shows an HTML page that enables the user to enter data bound for a servlet.

Listing 21.9 The DataEntry.html File

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<HTML>
 <HEAD>
  <TITLE>Passing Parameters to Java Servlets</TITLE>
 </HEAD>
 <BODY BGCOLOR="#FDF5E6">
 <H1 align="CENTER">
 Enter Values for all three Parameters
 </H1>

 <FORM action='/examples/servlet/PassParam'>
   Name:      <INPUT TYPE="TEXT" NAME="UserName"><BR><BR>
   Age:      <INPUT TYPE="TEXT" NAME="UserAge"><BR><BR>
   Favorite Sport: <INPUT TYPE="TEXT" NAME="UserSport"><BR><BR>
   <CENTER>
    <INPUT TYPE="SUBMIT">
   </CENTER>
 </FORM>
 
 </BODY>
</HTML>

The most interesting part of this HTML file is the <FORM> tag. The design of this feature predates Java servlets by several years. In the formative years of Web development, forms were heavily used with CGI and Perl on the server. The basic flow is fairly intuitive. The FORM tag contains an action value that tells which script the Web server is to run when the SUBMIT button is clicked. In this case, the action is to run a servlet stored in the examples application, called PassParam. On Tomcat, this means that this servlet will be stored in a classes directory immediately under the WEB-INF directory. Other Web servers use other naming conventions.

 <FORM action='/examples/servlet/PassParam'>

This form tag contains three data entry boxes, along with some text that tells you what belongs in each box.

   Name:      <INPUT TYPE="TEXT" NAME="UserName"><BR><BR>
   Age:      <INPUT TYPE="TEXT" NAME="UserAge"><BR><BR>
   Favorite Sport: <INPUT TYPE="TEXT" NAME="UserSport"><BR><BR>

Following these, a SUBMIT button is defined. When the user clicks on this button, the action is to be triggered. The browser processes this form and creates the HTTP containing the request.

   <CENTER>
    <INPUT TYPE="SUBMIT">
   </CENTER>

To execute this example, store this file in the webapps\examples\ directory and type the following line in the address box of a browser:

http://localhost:1776/examples/DataEntry.html

The browser will look like Figure 21.9.

Figure 21.9.

The Form tag causes data entry fields to be created on a Web page.

When you enter the data into the form and click the SUBMIT button, the following line will appear in the address line of the browser:

http://localhost:1776/examples/servlet/PassParam? 
UserName=Joe&UserAge=15&UserSport=Soccer

Notice that the parameters are passed right on the command line, providing proof that a GET HTTP command has been issued. We could have written this HTML page with the following FORM tag:

 <FORM action='/examples/servlet/PassParam' method='GET'>

The result would have been the same, however, because GET is the default form-handling method. The syntax of the method says that we want to call a servlet in the examples application called PassParam. As mentioned earlier in this section, the Web server will look for the file ...\webapps\examples\WEB_INF\classes\PassParam.class. Listing 21.10 shows the .java file that was used to create the PassParam.class file.

Listing 21.10 The PassParam.java Class

/*
 * PassParam.java
 *
 * Created on June 21, 2002, 5:25 PM
 */


import javax.servlet.*;
import javax.servlet.http.*;

/**
 *
 * @author Stephen Potts
 * @version
 */
public class PassParam extends HttpServlet
{
  
  /** Initializes the servlet.
  */
  public void init(ServletConfig config) throws ServletException
  {
   super.init(config);
   
  }
  
  /** Destroys the servlet. 
  */
  public void destroy()
  {
   
  }
  
  /** Processes requests for both HTTP <code>GET</code> 
  * and <code>POST</code> methods.
  * @param request servlet request
  * @param response servlet response
  */
  protected void processRequest(HttpServletRequest request,
                 HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   response.setContentType("text/html");
   java.io.PrintWriter out = response.getWriter();

    // output your page here
    out.println("<html>");
    out.println("<head>");
    out.println("<title>" + "Parameter Passing" +
                     "</title>");
    out.println("</head>");
    out.println("<body BGCOLOR=\"#FDF5E6\"\n>");
    out.println("<h1 ALIGN=CENTER>"); 
    out.println("Here are the Parameters"); 
    out.println("</h1>"); 
    out.println("<B>The UserName is </B>");
    out.println(request.getParameter("UserName") + "<BR>"); 
    out.println(" ");
    out.println("<B>The UserAge is </B>");
    out.println(request.getParameter("UserAge") + "<BR>"); 
    out.println(" "); 
    out.println("<B>The UserSport is </B>");
    out.println(request.getParameter("UserSport") + "<BR>"); 
    out.println(" ");
    out.println("</body>");
    out.println("</html>");

   out.close();
  }
  
  /** Handles the HTTP <code>GET</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doGet(HttpServletRequest request,
                 HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   processRequest(request, response);
  }
  
  /** Handles the HTTP <code>POST</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doPost(HttpServletRequest request,
                    HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   processRequest(request, response);
  }
  
  /** Returns a short description of the servlet.
  */
  public String getServletInfo()
  {
   return "Short description";
  }
  
} 

This servlet looks like the simple servlets already described in this chapter, but it has some new features. As usual, the real work is done in the processRequest() method, which is called by both the doGet() and doPost() methods. This method is passed to the HttpServletRequest and HttpServletResponse objects.

  protected void processRequest(HttpServletRequest request,
                 HttpServletResponse response)
  throws ServletException, java.io.IOException

The response object is how we will communicate back to the client's browser. The Web server will magically communicate anything printed to this object back to the client's browser.

   response.setContentType("text/html");
   java.io.PrintWriter out = response.getWriter();

Much of the output consists of simple static HTML statements, but there are several dynamic statements. The request object contains quite a bit of information that has been passed to the servlet from the browser. The most important parts of this information are the values of the parameters that were passed in from the HTML.

    out.println("<B>The UserName is </B>");
    out.println(request.getParameter("UserName") + "<BR>"); 
    out.println(" ");

Notice how the request object retrieves these values by the exact string names that were specified in the HTML. The HTML line for the age was

   Age:      <INPUT TYPE="TEXT" NAME="UserAge"><BR><BR>

The parameter that the getParameter() passed is the same name, "UserAge". The value that it returns will be a String containing exactly what the user entered into the browser.

    out.println("<B>The UserAge is </B>");
    out.println(request.getParameter("UserAge") + "<BR>"); 
    out.println(" "); 
    out.println("<B>The UserSport is </B>");
    out.println(request.getParameter("UserSport") + "<BR>"); 

The result of running the DataEntry.HTML page and clicking SUBMIT is shown in Figure 21.10.

Figure 21.10

The HttpServletRequest contains information that is being passed from the browser to the servlet.

The DataEntry.HTML page used the default HTTP GET command to communicate with the server. We can change that very easily to use the POST command instead. All that we have to do is modify the HTML as shown in Listing 21.11.

Listing 21.11 The DataEntryPost.HTML File

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<HTML>
 <HEAD>
  <TITLE>Posting Parameters to Java Servlets</TITLE>
 </HEAD>
 <BODY BGCOLOR="#FDF5E6">
 <H1 align="CENTER">
 Enter Values for all three Parameters
 </H1>

 <FORM action='/examples/servlet/PassParam' method='post'>
   Name:      <INPUT TYPE="TEXT" NAME="UserName"><BR><BR>
   Age:      <INPUT TYPE="TEXT" NAME="UserAge"><BR><BR>
   Favorite Sport: <INPUT TYPE="TEXT" NAME="UserSport"><BR><BR>
   <CENTER>
    <INPUT TYPE="SUBMIT">
   </CENTER>
 </FORM>
 
 </BODY>
</HTML>

Notice that only one line has changed:

 <FORM action='/examples/servlet/PassParam' method='post'>

The post method is telling the browser to generate a different set of HTTP commands to send to the server. This new version passes the parameters in the content of the HTTP communication, not in the address as we saw earlier. The URL being sent to the server now looks like the following:

http://localhost:1776/examples/servlet/PassParam

Notice that no changes were made to the servlet. The reason for this is that the Web server prepares the same request object regardless of which method is specified. A second reason is that we wrote the servlet with the same processing for both the doGet() and the doPost() methods. Be aware that the GET method will only allow 255 bytes to be passed. Anything longer will be truncated, therefore longer parameters must use the POST method.

Calling Other Classes from Servlets

The organization of servlets is a subject of some discussion among those of us who think about this kind of thing. One camp says that it is fine to place business logic in servlets, and the other says that the servlet itself should be reserved for communication purposes. There are distinct advantages to the second point of view.

  • Simplicity—The communication and housekeeping portions of a servlet are complex enough without adding business logic to them.

  • Object Orientation—Using classes to encapsulate functionality is the basic tenet of OO. All the benefits normally associated with OO flow from it.

  • Debugging—It is far simpler to debug an ordinary Java Class than it is to debug a servlet. Single-step debuggers are much easier to set up when ordinary classes are involved. A main() method can be written that instantiates the class in a similar way to the servlet in production.

To illustrate the OO approach to servlets, we will modify the PassParam class that you were introduced to earlier in this chapter. Listing 21.12 shows this new class.

Listing 21.12 The PassParam2 Class

/*
 * PassParam2.java
 *
 * Created on June 21, 2002, 5:25 PM
 */

import javax.servlet.*;
import javax.servlet.http.*;
import com.samspublishing.jpp.ch21;
/**
 *
 * @author Stephen Potts
 * @version
 */
public class PassParam2 extends HttpServlet
{
  
  /** Initializes the servlet. 
  */
  public void init(ServletConfig config) throws ServletException
  {
   super.init(config);
   
  }
  
  /** Destroys the servlet.
  */
  public void destroy()
  {
   
  }
  
  /** Processes requests for both HTTP <code>GET</code>
  * and <code>POST</code> methods.
  * @param request servlet request
  * @param response servlet response
  */
  protected void processRequest(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   response.setContentType("text/html");
   java.io.PrintWriter out = response.getWriter();
   
   System.out.println("Creating the HTMLBuilder");
   HTMLBuilder hb = new HTMLBuilder();
   String htmlOutput = hb.formatResponse(request);
   out.println(htmlOutput);
   System.out.println("Response was formatted by HTMLBuilder");
   
   
   out.close();
  }
  
  /** Handles the HTTP <code>GET</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doGet(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   processRequest(request, response); 
  }
  
  /** Handles the HTTP <code>POST</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doPost(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   processRequest(request, response);
  }
  
  /** Returns a short description of the servlet.
  */
  public String getServletInfo()
  {
   return "Short description";
  }
  
}

Compiling this class can be tricky. This class is not part of a package (except the default package), so it can be compiled in any directory that has visibility to the HTMLBuiler class. HTMLBuilder, which this class calls, is in the com.samspublishing.jpp.ch21 package, so move the PassParam2.java file to the directory just above the com/samspublishing/jpp/ch21 class and compile it there. If you placed this chapter's code in C:\com\samspublishing\jpp\ch21, you would move to the c:\ directory to compile it.

This class is identical to the PassParam class except for the contents of processRequest(). In this version, processRequest() does only servlet-type work, delegating the actual layout work to the HTMLBuilder class, which we will examine next. An instance of HTMLBuilder is created, and its formatResponse() method is called with the HttpServletRequest object passed in as a parameter. It returns a String object, which we print to the PrintWriter object.

  protected void processRequest(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   response.setContentType("text/html");
   java.io.PrintWriter out = response.getWriter();
   
   System.out.println("Creating the HTMLBuilder");
   HTMLBuilder hb = new HTMLBuilder();
   String htmlOutput = hb.formatResponse(request);
   out.println(htmlOutput);
   System.out.println("Response was formatted by HTMLBuilder");
   
   
   out.close();
  }

Several println() statements were added to this class. These statements appear in the Tomcat console when the servlet runs. This is a primitive, but effective, technique for debugging servlets. The real work has now been delegated to the HTMLBuilder class, which is shown in Listing 21.13.

/*
 * HTMLBuilder.java
 *
 * Created on June 25, 2002, 9:55 AM
 */

package com.samspublishing.jpp.ch21;

import javax.servlet.*;
import javax.servlet.http.*;


/**
 *
 * @author Stephen Potts
 * @version
 */
public class HTMLBuilder
{
  
  /** Creates new HTMLBuilder */
  public HTMLBuilder()
  {
  }
  
  public String formatResponse(HttpServletRequest request)
  throws ServletException, java.io.IOException
  
  {
   System.out.println("Entered into HTMLBuilder.formatResponse()");
   StringBuffer sb = new StringBuffer();
   
   // output your page here
   sb.append("<html>\n");
   sb.append("<head>\n");
   sb.append("<title>" + "HTML Formatting" +
   "</title>\n");
   sb.append("</head>\n");
   sb.append("<body BGCOLOR=\"#FDF5E6\"\n>\n");
   sb.append("<h1 ALIGN=CENTER>\n");
   sb.append("Here are the Parameter2");
   sb.append("</h1>\n");
   sb.append("<B>The UserName2 is </B>\n");
   sb.append(request.getParameter("UserName") + "<BR>\n");
   sb.append(" ");
   sb.append("<B>The UserAge2 is </B>\n");
   sb.append(request.getParameter("UserAge") + "<BR>\n");
   sb.append(" ");
   sb.append("<B>The UserSport2 is </B>\n");
   sb.append(request.getParameter("UserSport") + "<BR>\n");
   sb.append(" ");
   sb.append("</body>\n");
   sb.append("</html>\n");
   System.out.
          println("Returning from HTMLBuilder.formatResponse()");
   
   return sb.toString();
  }
}

This class is created in a package. This will impact its deployment in the Tomcat directory structure. In Java, the package name and the class name form the real name of the program or servlet. The directory structure must match the package name, according to the rules of Java.

package com.samspublishing.jpp.ch21;

The formatResponse() method takes the HttpServletRequest object as a paramater, and it returns a String object. The fact that this class is not a servlet does not impact its capability to make method calls on the HttpServletRequest object. This is an object like any other in Java and can be passed as a parameter as is done here.

  public String formatResponse(HttpServletRequest request)
  throws ServletException, java.io.IOException

We create a StringBuffer class because we will be appending a lot of strings to it. StringBuffer's performance is so much better than the String class's, that it makes sense to use it here. In fact, programmers who do serial appends to String objects risk embarrassment during code review.

   StringBuffer sb = new StringBuffer();
   
   // output your page here
   sb.append("<html>\n");
   sb.append("<head>\n");

The request object's methods, such as getParameter(), are available inside this class also.

   sb.append(request.getParameter("UserName") + "<BR>\n");

Before returning, we transform the StringBuffer into a String object and return it to the servlet for insertion into the response object.

   return sb.toString();

To get this to work we also have to modify the DataEntry.html file, as shown in Listing 21.14.

Listing 21.14 The DataEntry2.html File

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<HTML>
 <HEAD>
  <TITLE>Passing Parameters to Java Servlets</TITLE>
 </HEAD>
 <BODY BGCOLOR="#FDF5E6">
 <H1 align="CENTER">
 Enter Values DataEntry2
 </H1>

 <FORM action='/examples/servlet/PassParam2'>
   Name2:      <INPUT TYPE="TEXT" NAME="UserName"><BR><BR>
   Age2:      <INPUT TYPE="TEXT" NAME="UserAge"><BR><BR>
   Favorite Sport2: <INPUT TYPE="TEXT" NAME="UserSport"><BR><BR>
   <CENTER>
    <INPUT TYPE="SUBMIT">
   </CENTER>
 </FORM>
 
 </BODY>
</HTML>

The only major change is the calling of the PassParam2 servlet instead of the PassParam servlet.

 <FORM action='/examples/servlet/PassParam2'>

The deployment of this servlet and class is a bit different. The PassParam2.class file can be placed in the ...\webapps\examples\WEB-INF\classes directory, and the HTML file can be placed in the ...\webapps\examples directory as before. The HTMLBuilder class, however, is in a package. The rules of packages state that the class file must be stored in a directory structure that matches the package name. The package name for HTMLBuilder is com.samspublishing.jpp.ch21. This requires that this class be placed in the directory:

...\webapps\examples\WEB-INF\classes\com\samspublishing\jpp\ch21

This makes for a long subdirectory string, but Tomcat can find what it needs very easily.

You run this by entering the name of the HTML file in the address line of the browser:

http://localhost:1776/examples/DataEntry2.html

When you click the SUBMIT button, the URL that appears is

http://localhost:1776/examples/servlet/PassParam2? 
_UserName=Jake&UserAge=9&UserSport=Soccer

The browser output is nearly identical to Figures 21.9 and 21.10, so they won't be repeated here. This application added several println() statements for debugging purposes. The Tomcat console, which is shown here, is where these statements appear.

Creating the HTMLBuilder
Entered into HTMLBuilder.formatResponse()
Returning from HTMLBuilder.formatResponse()
Response was formatted by HTMLBuilder

It is often useful to add println() statements to your code to monitor its progress and to track down bugs.

Using Cookies to Maintain State

The fact that the HTTP protocol is stateless is one of its finest features. The simplicity of this approach makes it an ideal tool for delivering content quickly.

This statelessness is also a hindrance when you need to perform a task that has to span several Web pages. It would be nice if you could identify yourself to the server so that it could pick up where it left off in the previous transaction, instead of having to start over every time.

The browser writers addressed this issue first when they introduced the idea of cookies. Cookies are small files that live on the client's hard drive, which identify the user to a specific Web application. The server sends the cookie to the browser in response to the initial request. Subsequent requests send the same cookie back to the server, which enables the server to identify these requests as being from the same requester.

Java supports the creation and manipulation of cookies via the javax.servlet.http.Cookie class. About a dozen methods are defined by this class, but the constructor, setValue() and getValue(), are the most commonly used. Listing 21.15 shows how cookies are used to store the state of an application.

Listing 21.15 The SpecialDiet.java Class

/*
 * SpecialDiet.java
 *
 * Created on June 25, 2002, 1:27 PM
 */

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

/**
 *
 * @author Stephen Potts
 * @version
 */
public class SpecialDiet extends HttpServlet
{
  
  /** Initializes the servlet.
  */
  public void init(ServletConfig config) throws ServletException
  {
   super.init(config);
   
  }
  
  /** Destroys the servlet.
  */
  public void destroy()
  {
   
  }
  
  
  /** Handles the HTTP <code>GET</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doGet(HttpServletRequest request,
                HttpServletResponse response)
  throws ServletException, java.io.IOException
  {

  }
  
  /** Handles the HTTP <code>POST</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doPost(HttpServletRequest request,
                  HttpServletResponse response) 
  throws ServletException, java.io.IOException
  {
   response.setContentType("text/html");
   Cookie myCookie = new Cookie("null", "null");
   
   Enumeration keys;
   String key, value;
   keys = request.getParameterNames();
   while (keys.hasMoreElements())
   {
     key = (String)keys.nextElement();
     value = request.getParameter(key);
     if(!key.equals("btnSubmit"))
     {
      System.out.println("value= " + value + " key= " + key);
      myCookie = new Cookie(value,key);
      response.addCookie(myCookie);
     }
   }
   response.sendRedirect(
       "http://localhost:1776/examples/servlet/SpecialDiet2");
  }
  
  
  /** Returns a short description of the servlet.
  */
  public String getServletInfo()
  {
   return "Short description";
  }
  
} 

This is a typical servlet until you get into the doPost() method. A Cookie object is declared and used to store several cookies.

   Cookie myCookie = new Cookie("null", "null");

We step through each parameter and create a cookie that stores the current value.

   Enumeration keys;
   String key, value;
   keys = request.getParameterNames();
   while (keys.hasMoreElements())
   {
     key = (String)keys.nextElement();

We get the parameters from the request object.

     value = request.getParameter(key);

The only key that we don't want to create a cookie for is the OK button.

     if(!key.equals("btnSubmit"))
     {
      System.out.println("value= " + value + " key= " + key);

We store the value and the key in the cookie and add it to the response object.

      myCookie = new Cookie(value,key);
      response.addCookie(myCookie);

Finally, we call the sendRedirect() method to another servlet that displays all the cookies.

   response.sendRedirect(
      "http://localhost:1776/examples/servlet/SpecialDiet2");

This line causes a different servlet, SpecialDiet2, to be called. Because we don't specify a method, doGet() will be called. Listing 21.16 shows this program.

Listing 21.16 The SpecialDiet2 Class

/*
 * SpecialDiet2.java
 *
 * Created on June 25, 2002, 1:27 PM
 */

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

/**
 *
 * @author Stephen Potts
 * @version
 */
public class SpecialDiet2 extends HttpServlet
{
  
  /** Initializes the servlet.
  */
  public void init(ServletConfig config) throws ServletException
  {
   super.init(config);
   
  }
  
  /** Destroys the servlet.
  */
  public void destroy()
  {
   
  }
  
  
  /** Handles the HTTP <code>GET</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doGet(HttpServletRequest request,
                  HttpServletResponse response) 
  throws ServletException, java.io.IOException
  {
   response.setContentType("text/html");
   PrintWriter out = response.getWriter();
   
   Cookie cookies[];
   cookies = request.getCookies();
   
   System.out.println("Creating the SpecialDiet HTML");
   
   // output your page here
   out.println("<html>");
   out.println("<head>");
   out.println("<title>" + "Your Diet Choices" +
   "</title>");
   out.println("</head>");
   out.println("<body BGCOLOR=\"#FDF5E6\"\n>");
   out.println("<h1 ALIGN=CENTER>");
   out.println("Here are your choices");
   out.println("</h1>");
   for (int i=0; i< cookies.length; i++)
   {
     System.out.println(cookies[i].getName()+
             " " + cookies[i].getValue() + "<BR>");
     out.println(cookies[i].getName()+
             " " + cookies[i].getValue() + "<BR>");
     out.println(" ");
   }
   out.println("</body>");
   out.println("</html>");
   
   out.close();

  }
  
  /** Handles the HTTP <code>POST</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doPost(HttpServletRequest request,
                  HttpServletResponse response)
  throws ServletException, java.io.IOException
  {

  }
  
  
  /** Returns a short description of the servlet.
  */
  public String getServletInfo()
  {
   return "Short description";
  }
  
}

This servlet is ordinary also, except for the cookie-handling code. We declared an array of Cookie objects called cookies, and then called the HttpServletRequest class's getCookies() method.

   Cookie cookies[];
   cookies = request.getCookies();

In the midst of creating the HTML code, we loop through and print every cookie that was sent.

   for (int i=0; i< cookies.length; i++)
   {
     System.out.println(cookies[i].getName()+ 
              " " + cookies[i].getValue() + "<BR>");
     out.println(cookies[i].getName()+
              " " + cookies[i].getValue() + "<BR>");
     out.println(" ");
   }

The HTML that is used to gather the user input is shown in Listing 21.17.

Listing 21.17 The ChooseDiet.HTML File

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<HTML>
 <HEAD>
  <TITLE>Choose Your Dietary Preference</TITLE>
 </HEAD>
 <BODY BGCOLOR="#FDF5E6">
 <H1 align="CENTER">
 Do you have special dietary needs?:
 </H1>

 <FORM action='/examples/servlet/SpecialDiet' method='post'>
 <TABLE cellspacing='5' cellpadding='5'>
 <TR>
   <TD align='center'><B>Choose one or more</B></TD>
   <TD align='center'><B></B></TD>
   <TD align='center'><B></B></TD>
 </TR>
 <TR>
   <TD align='center'><INPUT TYPE='Checkbox'
            NAME="losodium" VALUE="loso117"></TD>
   <TD align='center'>Delicious Low-Sodium Pizza</TD>
 </TR>
 <TR>
   <TD align='center'><INPUT TYPE='Checkbox'
            NAME="lofat" VALUE="lofat118"></TD>
   <TD align='center'>Delicious Lo-Fat Chicken</TD>
 </TR>
 <TR>
   <TD align='center'><INPUT TYPE='Checkbox'
            NAME="vegan" VALUE="vegan119"></TD>
   <TD align='center'>Delicious Vegetarian Lasagna</TD>
 </TR>
</TABLE>
<HR><BR>
<CENTER>
<INPUT type='SUBMIT' name='btnSubmit' value='OK'>
<BR><BR>
<A href='/examples/servlet/SpecialDiet2'>View Current Choices</A>
</CENTER>
</FORM>
</BODY>
</HTML>

Notice that the method on the Form is Post. This is so that doPost() will be called on the servlet.

 <FORM action='/examples/servlet/SpecialDiet' method='post'>

We also included a link to the output servlet from this page:

<A href='/examples/servlet/SpecialDiet2'>View Current Choices</A>

The result of running the ChooseDiet.html is shown here in Figure 21.11.

Figure 21.11

The ChooseDiet.html form uses check boxes to gather user input.

The SpecialDiet servlet has no visible result. It calls the SpeciaDiet2 servlet, which displays the values and the keys that were stored in the cookies.

Cookies provide a simple way to store small amounts of data using the browser. You can see how this approach might become unmanageable if the amount of state data were to become large. The Session object uses cookies to provide a more elegant solution for larger amounts of data.

Figure 21.12

The SpecialDiet2 servlet displays the contents of the cookies.

Using Session Objects to Maintain State

The Java servlet API gives us a way to manage state on the server side through the use of the HttpSession interface. This interface contains the usual dozen methods, but the most important ones are the constructor, getAttribute(), and setAttribute(). Internally, the Web server uses cookies to determine which of all the potentially active session objects is the one to provide to a particular servlet, but this processing is invisible to the programmer for security reasons.

The basic flow of a session-oriented servlet is that one servlet will create the session object and place data in it. Subsequent calls to the Web server from that browser will have access to that stored data if they need it. Session objects differ from cookies in that they use the cookie to store only a browser identifier. All the other data is stored in the Web server. This means that the data will not be available if the Web server is restarted. If restarting could cause problems in your application, consider storing the data to a file or database periodically and reloading it when needed.

We will modify the SpecialDiet servlet to use sessions instead of cookies and call it SpecialDietSession. This servlet is shown in Listing 21.18.

Listing 21.18 The SpecialDietSession Servlet

/*
 * SpecialDietSession.java
 *
 * Created on June 25, 2002, 1:27 PM
 */

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

/**
 *
 * @author Stephen Potts
 * @version
 */
public class SpecialDietSession extends HttpServlet
{
  
  /** Initializes the servlet.
  */
  public void init(ServletConfig config) throws ServletException
  {
   super.init(config);
   
  }
  
  /** Destroys the servlet.
  */
  public void destroy()
  {
   
  }
  
  
  /** Handles the HTTP <code>GET</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doGet(HttpServletRequest request,
                 HttpServletResponse response)
  throws ServletException, java.io.IOException
  {

  }
  
  /** Handles the HTTP <code>POST</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doPost(HttpServletRequest request,
                  HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   //Get the Session Object
   HttpSession httpSess = request.getSession(true);
   Integer numItems = (Integer) httpSess.getAttribute("numItems");
   if (numItems== null)
   {
     numItems = new Integer(0);
   }
   response.setContentType("text/html");
   PrintWriter out = response.getWriter();
   
   Enumeration keys;
   String key, value;
   keys = request.getParameterNames();
   while (keys.hasMoreElements())
   {
     key = (String)keys.nextElement();
     value = request.getParameter(key);
     if(!key.equals("btnSubmit"))
     {
      System.out.println("SDS value= " + numItems +
                      " " + value + " key= " + key);
      httpSess.setAttribute("Item" + numItems , key + " " + value);
      numItems = new Integer(numItems.intValue()+ 1);
     }
   }
   httpSess.setAttribute("numItems", numItems);
       // output your page here
    out.println("<html>");
    out.println("<head>");
    out.println("<title>" + "SpecialDietSession" +
                     "</title>");
    out.println("</head>");
    out.println("<body BGCOLOR=\"#FDF5E6\"\n>");
    out.println("<h1 ALIGN=CENTER>"); 
    out.println("Session Object Populated"); 
    
    out.println("<CENTER>");
    out.println("<BR><BR>");
    out.println("<A href=
     '/examples/servlet/SpecialDietSession2'>
       View Your Choices</A>");
    out.println("</CENTER>");

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

   out.close();

   
  }
  
  
  /** Returns a short description of the servlet. 
  */
  public String getServletInfo()
  {
   return "Short description";
  }
  
}

This servlet is fairly normal with the exception of the HttpSession processing. We use the HttpServletRequest object to get a handle to the HttpSession object. The Boolean value in the parameter to the getSession() method call states that a new session object is to be created if none exists for this client.

   HttpSession httpSess = request.getSession(true);

We declare an attribute that will be used to track the number of attributes in the session object.

   Integer numItems = (Integer) httpSess.getAttribute("numItems");

We use an enumeration to process all the parameters in the request object.

   Enumeration keys;
   String key, value;
   keys = request.getParameterNames();
   while (keys.hasMoreElements())
   {
     key = (String)keys.nextElement();
     value = request.getParameter(key);

We want to store every parameter except btnSubmit.

     if(!key.equals("btnSubmit"))
     {
      System.out.println("SDS value= " + numItems +
               " " + value + " key= " + key);

The setAttribute() method is the one that adds the parameters to the session object. We are adding an artificial name for each key-value pair called Itemx, where x is an increasing number. This is for convenience when retrieving all the attributes later.

    httpSess.setAttribute("Item" + numItems , key + " " + value);

We increment a counter that we will store after the loop is complete.

      numItems = new Integer(numItems.intValue()+ 1);
     }
   }
   httpSess.setAttribute("numItems", numItems);

The servlet is called by the ChooseDietSession.html file, which is shown in Listing 21.19.

Listing 21.19 The ChooseDietSession.html File

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<HTML>
 <HEAD>
  <TITLE>Choose Your Dietary Preference</TITLE>
 </HEAD>
 <BODY BGCOLOR="#FDF5E6">
 <H1 align="CENTER">
 Do you have special dietary needs?:
 </H1>

 <FORM action='/examples/servlet/SpecialDietSession'
       method='post'>
 <TABLE cellspacing='5' cellpadding='5'>
 <TR>
   <TD align='center'><B>Choose one or more</B></TD>
   <TD align='center'><B></B></TD>
   <TD align='center'><B></B></TD>
 </TR>
 <TR>
   <TD align='center'><INPUT TYPE='Checkbox'
            NAME="losodium" VALUE="loso117"></TD>
   <TD align='center'>Delicious Low-Sodium Pizza</TD>
 </TR>
 <TR>
   <TD align='center'><INPUT TYPE='Checkbox'
             NAME="lofat" VALUE="lofat118"></TD>
   <TD align='center'>Delicious Lo-Fat Chicken</TD>
 </TR>
 <TR>
   <TD align='center'><INPUT TYPE='Checkbox'
             NAME="vegan" VALUE="vegan119"></TD>
   <TD align='center'>Delicious Vegetarian Lasagna</TD>
 </TR>
</TABLE>
<HR><BR>
<CENTER>
<INPUT type='SUBMIT' name='btnSubmit' value='OK'>
<BR><BR>
<A href='/examples/servlet/SpecialDietSession2'>
   View Current Choices</A>
</CENTER>
</FORM>
</BODY>
</HTML>

Figure 21.13 shows what the ChooseDietSession.html file looks like when displayed.

Figure 21.13

The ChooseDietSession HTML file gives the user the choices and calls SpecialDietSession.

At the end of the SpecialDietSession servlet, a message is displayed back to the user that contains a hyperlink to the SpecialDietSession2 servlet.

out.println(
"<A href='/examples/servlet/SpecialDietSession2'>
    View Your Choices</A>");

Listing 21.20 shows this display-oriented servlet.

After the OK button is clicked, you will be taken to a confirmation screen as shown in Figure 21.14.

Figure 21.14

The SpecialDietSession servlet displays a confirmation page that contains a hyperlink to view the results.

Listing 21.20 The SpecialDietSession2 Servlet

/*
 * SpecialDietSession2.java
 *
 * Created on June 25, 2002, 1:27 PM
 */

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

/**
 *
 * @author Stephen Potts
 * @version
 */
public class SpecialDietSession2 extends HttpServlet
{
  
  /** Initializes the servlet.
  */
  public void init(ServletConfig config) throws ServletException
  {
   super.init(config); 
   
  }
  
  /** Destroys the servlet.
  */
  public void destroy()
  {
   
  }
  
  
  /** Handles the HTTP <code>GET</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doGet(HttpServletRequest request,
                HttpServletResponse response)
  throws ServletException, java.io.IOException
  {
   HttpSession httpSess = request.getSession(true);
   response.setContentType("text/html");
   PrintWriter out = response.getWriter();
   
   
   System.out.println("Creating the SpecialDiet HTML");
   
   // output your page here
   out.println("<html>");
   out.println("<head>");
   out.println("<title>" + "Your Diet Choices" +
   "</title>");
   out.println("</head>");
   out.println("<body BGCOLOR=\"#FDF5E6\"\n>");
   out.println("<h1 ALIGN=CENTER>");
   out.println("Here are your choices");
   out.println("</h1>");
   Integer numItems = (Integer) httpSess.getAttribute("numItems");

   for (int i=0; i< numItems.intValue(); i++)
   {
     String itemContents =
            (String)httpSess.getAttribute("Item" + i);
     System.out.println(itemContents + "<BR>");
     out.println("Item" + i + "= " + itemContents + "<BR>");
     out.println(" ");
   }
   out.println("</body>");
   out.println("</html>");
   
   httpSess.invalidate();
   
   out.close();

  }
  
  /** Handles the HTTP <code>POST</code> method.
  * @param request servlet request
  * @param response servlet response
  */
  protected void doPost(HttpServletRequest request,
            HttpServletResponse response)
  throws ServletException, java.io.IOException
  {

  }
  
  
  /** Returns a short description of the servlet.
  */
  public String getServletInfo()
  {
   return "Short description";
  }
  
}

This servlet mostly displays code. Its main feature is that it steps through the entries of the session object and outputs them to the browser.

   Integer numItems = (Integer) httpSess.getAttribute("numItems");

   for (int i=0; i< numItems.intValue(); i++)
   {
     String itemContents =
            (String)httpSess.getAttribute("Item" + i);
     System.out.println(itemContents + "<BR>");
     out.println("Item" + i + "= " + itemContents + "<BR>");
     out.println(" ");
   }

The getAttribute() method is the main player here. The contents of the session object are referenced by name and printed.

At the end, we invalidated the session object, which causes the information in it to be purged. If we didn't do this, the entries would continue to be added each time we ran the servlets, which is not the desired result. Figure 21.15 shows the result of running the SpecialDietSession2.

Figure 21.15

The SpecialDietSession2 servlet displays the results.

The contents of the session object are displayed both for you to inspect and to prove that they retained their values across different servlet calls.

Summary

This chapter has introduced you to the world of servlet development. We started with a discussion of how servlets worked. Following that, you learned how to set up your development environment.

You learned how the HTTP protocol, the language of servlets, works. Following that, you learned how to create servlets using both the GenericServlet class and the HttpServlet class.

We covered how to create servlets that called other classes and how to deploy those classes. Then you learned how to preserve servlet state in the browser using cookies. Finally, you learned how to use the HTTPSession interface to store data on the server between servlet calls by the same browser.

Review Questions

  1. What is the difference between a servlet and a Java application running on the server?

  2. What is servlet container?

  3. What is the difference between the HTTPServlet class and the GenericServlet class?

  4. What is a session object?

  5. What is the difference between a cookie and a session object?

Exercises

  1. Create a servlet that echoes your name when called.

  2. Create a servlet that lets you choose toppings on a pizza.

  3. Expand the pizza servlet to use cookies to remember your last order and ask you if you want the same toppings this time.

  4. Modify the pizza servlet to use a session to accomplish this.

  5. Move the creation of the HTML to be returned by the pizza servlet to a class in a package.


About the Authors

Steve Haines has worked in the enterprise software industry for the past eight years and has been focusing on Java since 1997. He has been filling key architectural roles in the areas of B2B e-commerce, high-speed Internet marketing, application monitoring and diagnosis, and robust client and server-side image layout and management over the past few years. He is currently the J2EE Domain Architect for Quest Software and is responsible for defining the expert rules for tuning and monitoring Enterprise Java applications and application servers.

He is the author of Que Publishing's Java 2 from Scratch and has numerous articles on InformIT.com in the areas of Java Swing and Enterprise Java. He shares author credits on Java Web Services Unleashed, C++ Unleashed, Sams Teach Yourself C++ in 21 Days, and Sams Teach Yourself Java in 21 Days. He has also worked as a technical editor for Pearson Education in areas of Java, Enterprise Java, Network Communications, C++, and video-game programming. Steve has taught all aspects of Java programming from basic certification training through Database, Web Development, and Enterprise JavaBeans at Learning Tree University (LTU). Steve recently enrolled in a Bachelor's of Biblical Studies at Calvary Chapel Bible College.

Steve Potts is an independent consultant, author, and Java instructor in Atlanta, Georgia. Steve received his Computer Science degree in 1982 from Georgia Tech. He has worked in a number of disciplines during his 20-year career, with manufacturing being his deepest experience. Steve has consulted for such companies as Home Depot, Disney, and IBM. His previous books include Java Unleashed and Java 1.2 How-To. He can be reached via email at stevepotts@mindspring.com.

Source of this material

This is Chapter 21: Servlets from the book Java 2 Primer Plus (ISBN: 0-672-32415-6) written by Steven Haines, published by Sams Publishing.

To access the full Table of Contents for the book.


Other Chapters from Sams Publishing:

Web Services and Flows (WSFL)
Overview of JXTA
Introduction to EJBs
Processing Speech with Java
The Java Database Control in BEA Weblogic
Databases and Tomcat
Working with JAX-RPC

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date