14 Servlets and Java Server Pages

For a variety of reasons, many enterprises are using the Internet as a model for new application development. The major reason is ease of deployment. Every machine with a browser and connection to the server has immediate access to the application. No messy software has to be installed and kept up to date on each machine. The browser provides a feature-rich environment for sophisticated and user-friendly applications. As more and more people become Internet savvy, education and training costs are dramatically reduced.

Java plays a key role in this new paradigm. Java running on the server provides a robust and high-performance environment for developing and running applications. Although servlets and Java Server Pages (JSPs) can be used for both presentation and business logic, good design principles usually require a separation of the two. Servlets and JSPs in most designs are used for presentation logic. Business logic in the full-blown Java Enterprise Edition (JEE) environment is usually handled by Enterprise JavaBeans, the subject of the next chapter.

BROWSERS AND WEB SERVERS

To do Web development, you need to understand how Web servers work and how they interact with their clients, the browsers. Once this understanding is in place, you will readily see how servlets and JSPs fit into the picture.

The simplest requirement of a Web server is to serve static HTML pages and images. In doing this activity, Web servers are really file servers. The files they serve are text files containing HTML and their associated images and resources. The clients they serve are usually browsers. The protocol for the communication is Hypertext Transfer Protocol (HTTP). Modern Web servers, of course, can do much more than simply serve files, but let’s stay with the simplest communication for the moment.

The client, usually a browser, opens a connection to the server. After it gets a connection, it sends a request that is formatted correctly for HTTP. The server responds according to what was requested, in a form that is formatted correctly for the protocol. The connection is closed.

Each request from the client and response by the server is an autonomous communication. Each runs independently from all that went before it and from all that came after it. The transaction is stateless. No persistent connection exists between the client and the Web server. No “memory” of other transactions is built into the protocol. The protocol was designed this way for speed.

Now you’ll dissect a simple transaction to a deeper level. Let’s pretend you have installed a Web server on your machine and have placed a simple HTML document called resume.html in the root directory that the Web server uses to serve files. This directory is configurable for each Web server. The machine is running at IP address 90.121.111.5.

First, the client starts a request of the Web server by opening a TCP/IP connection to the Web server.

The address of the connection is expressed as a URL. The URL is the standard addressing system used to locate resources on the Internet. The syntax for a URL is [protocol]:[resource]. The protocol is the access scheme or method. Common protocols are http, ftp, gopher, and WAIS.

The part after the colon is interpreted according to the access scheme. In general, two slashes after the colon introduce a hostname or hostname:port. The hostname can be an IP address, such as 90.121.111.5, or a name, such as www.yahoo.com. If it is a name, the name must be translated to a real IP address. A domain name system (DNS) accomplishes this task. The port number is the socket through which the server is listening for connections. In most cases, the port number can be omitted because each protocol has its default port. The browser will attempt to establish the connection on the default port if the port number is absent in the URL. As long as the server is listening on the default port, the connection will be made. The standard port for the HTTP is port 80.

For HTTP, the next part is a pathname. In this simple example, this maps to the pathname of a file on the server. The file can contain any type of data. Browsers know what to do with HTML and GIF and JPEG images. Browsers may pass the file to an external viewer if the appropriate plug-in for the file type has been installed. This is what happens, for example, when you view a PDF file in the Acrobat viewer. Once you have it installed, it is invoked to display the contents of the file. A pound sign (#) following the pathname indicates a particular position on the HTML page.

The URL, after the pathname, may also have a query string preceded by a question mark (?). A query string is used when you are running a program on the Web server, instead of serving a page. So let’s stay with the simple example for a moment.

You type the following into your browser’s address window: http://90.121.111.5/resume.html. The browser tries to open the connection to the Web server running on port 80 at 90.121.111.5.

After the connection is opened, the browser sends the request in correctly formatted HTTP. In the example, the request is for a file called resume.html. The browser looks for and finds the file resume.html in its root directory, where it serves files. The Web server reads the file and creates a response. Included in the response is the output type that is being returned to the browser. A Multipurpose Internet Media Extension (MIME) type placed in the response provides information about the type of data the browser can expect. In this case, the data type is text/html. This information is included in the header portion of the response. Web servers map file extensions to MIME types. An image file might have the MIME type image/gif.

How the file is rendered by the browser depends on the browser, but only certain types are interpreted directly by most browsers. These include HTML and images in GIF or JPEG format. A file whose type is not recognized directly by the browser may be passed to an external “viewer” application, such as a sound player.

The browser receives the response, reads the HTML, and formats the display. The transaction is complete and the connection between the browser and the server is closed.

As mentioned earlier, the URL after the pathname may have a query string. The query string consists of one or more parameters followed by their values. Each parameter consists of a parameter name followed by an equals sign and the parameter value. Parameters are distinguished from each other by an ampersand (&).

For example, the query string ?x=5&y=7&z=1+2+3 has three parameters: x, y, and z. The parameter x has the value of 5; y has the value of 7. The parameter z is an array with values 1, 2, and 3.

The types of characters that can be passed in a query string are restricted to alphanumeric characters, certain reserved characters (:/?#”<>%+), and a few other characters ($-_.&+). If you need to pass anything else, it must be encoded. Characters are encoded as a “%” followed by two hexadecimal digits that represent the value of the character.

The browser request can be in one of two forms, GET and POST. A GET request is simply a request for data as identified in the URL. A POST request includes additional information in the request, in the message body. For example, if you enter information in a Web search portal and click the Search button, your search terms are sent in the message body that is included in the POST request to the search Web site.

THE SERVLET AS TRANSACTION PROCESSOR

To oversimplify things a little, a servlet is a Java program invoked by a Web server to respond to a request from a browser. A servlet responds to requests from the browser and builds HTML output. It is transaction-based. The request arrives; the servlet processes it and builds the response. The Web server routes the response back to the browser. The transaction is over. No persistent connection exists between the Web server and the servlet or between the servlet and the browser.

Since a servlet is a Java program, it must run in a Java VM. The VM it runs in is a specialized environment called a servlet engine. The role of the servlet engine is to provide the infrastructure and framework for all the servlets that are required for a Web site. The servlet engine loads the servlet, initializes it, invokes it, and routes the generated response back to the Web server.

The servlet and the servlet engine are intimately integrated with the Web server. This integration can take several forms:

  1. If the Web server is written in Java, it probably has a servlet engine integrated directly into it.

  2. If the Web server is written in some other language, it will need to have an extension to connect the Web server with the servlet engine. In this case, the servlet runs outside the Web server, and the Web server communicates with it through some protocol, usually TCP/IP. Most servlet engines supply extensions or connectors to most of the popular Web servers.

  3. Some servlet engines can themselves operate as Web servers. Functionally, this isn’t different from being a Web server written in Java with an integrated servlet engine. The difference is that the Web server part of the servlet is usually not highly optimized. The servlet engine works fine as a Web server for development, testing, and low-transaction-volume situations, but it would be better deployed in a high-transaction-volume situation as an extension to a Web server written in native platform code.

SERVLET PROTOCOL

A servlet is invoked as a URL, much like a static page or image file is invoked. In the configuration between the Web server and the servlet engine, virtual mappings are created. For example, the Web server may be configured to pass everything with the directory name of servlet to the servlet engine. The servlet engine then maps the name following the directory name to the actual servlet class that is to process the request. For example, the request for http://www.mywebsite.com/servlet/Start goes to the Web server. The Web server examines the request and sees the directory name servlet. It knows it must pass the request to the servlet engine. The servlet engine examines the request and sees the name Start after the virtual directory name. In its configuration, for example, it knows it must pass the request to “com.mywebsite.servlets.WelcomeServlet.” This path is illustrated in Figure 14.1.

Image

FIGURE 14.1
How the browser interacts with the Web server.

Servlets primarily receive HTML GET and POST requests that originate from browser forms. GET requests pass their parameters on the command line, for example, http://www.mywebsite.com/servlet/Start?parm1=1&parm2=2. POST requests pass their parameters in a data stream. In either case, the parameters are passed as name-value pairs and are encoded.

To create a servlet, you extend HttpServlet and override the service() or the doGet()/doPut() methods. You will need to import javax.servlet and javax.servlet.http packages to have this compile. These packages are found in the JEE SDK. The following is a simple servlet:

public class WelcomeServlet extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res) throws
   IOException, ServletException {
   res.setContentType("text/html");
          PrintWriter out = res.getWriter();
          out.println("<html>");
          out.println("<body>");
          out.println("<head>");
          out.println("<title>" + "Welcome Page" + "</title>");
          out.println("</head>");
          out.println("<body>");
          out.println("<h1> Welcome Page </h1><hr>");
          out.println("Welcome to the web site");
          out.println("</body>");
          out.println("</html>");
}
}

This servlet is very simple. It sets the content type in the response header so that the browser knows what type of data (that is, the MIME type) will follow. It then gets the PrintWriter associated with the HttpResponse object and uses the writer to write the HTML to the browser. The Web server is ultimately responsible for delivering the stream of HTML to the browser.

The preceding code would work fine if your servlet received only GET requests. The doGet() method would not be called for a POST request. You would need to override doPost() to receive the POST request.

The servlet engine initializes the servlet once when it is first loaded. The init() method can receive runtime parameters just like applets and do any one-time initialization required for the servlet. Once they are loaded, servlets stay loaded unless the servlet engine decides to shut them down. Servlets are handed requests from a thread pool, which is both good and bad. The good part is that the startup overhead for new requests is minimal. The bad part is that you need to be concerned about trashing your internal data if two service requests start executing simultaneously.

Remember that only one copy of your servlet is in the memory of the VM. If browser number 1’s request comes to the servlet and you set a value in your class instance during the processing of that request, that value will still be set when browser number 2’s request is handed to your servlet. In reality, the situation is even more complicated. Depending upon the thread-switching mechanisms in place in the VM, request number 2 might actually change the value of your variables even while request number 1 is still being processed. You might wonder how anyone can ever code in this environment. Although several solutions exist to the problem of reentrancy, the most common solution and the easiest is to create a session.

The servlet engine has the ability to create a Session object that is associated with the session between the browser and the Web server. A session is a time-sensitive association between an instance of a browser and the Web site. This Session object can exist across the interactions between the browser and the Web server. Typical logic is to create a Session object when someone first enters a site. The HttpRequest object has a method that returns the session if it exists or creates it if it doesn’t exist.

HttpSession session = req.getSession();

Once you have a session, you can put variables and objects in it:

String userId = "auser";
session.setAttribute("userId ", userId);

You can also retrieve values from it:

String userId = (String) session.getAttribute("userId ");

Variables can be simple or complex. You could, for example, create a class that contains all the variables that need to exist across interactions between the browser and the Web server and store an instance of the class in the session when the user first enters the Web site. For every interaction after that, you retrieve the instance associated with the session and use it for the logic. Since each user has a unique session and a unique instance of the class containing your variables, you can act on all the variables in the instance without worrying about trashing the variables associated with a different user.

Image

If you have experience in programming CICS or IMS in an IBM environment or similar technologies on other platforms, you may notice considerable similarity between a servlet and a mainframe TP program. In CICS, each execution of the program is a transaction unto itself. No permanent connection exists between the user at the terminal and the program. CICS makes use of the COMMAREA to store data between executions, just as a servlet uses the Session object.

JAVA SERVER PAGES

Java Server Pages (JSPs) came about with the recognition that large Web projects often required many different types of expertise. Most Web designers are not programmers, and most programmers are not good Web designers. In addition, placing HTML code inside of Java print statements is tedious (although some packages have been developed to simplify this), and it requires recompilation every time the appearance of the Web page needs to change. Imagine having to recompile to change background colors or add an icon.

A JSP typically looks more like HTML than Java, although it is possible to embed a significant amount of Java code into the page. Following is the code for an enhanced Welcome page you might display after a user has logged into the site and you’ve stored the user ID in the Session object.

<HTML><HEAD>
<TITLE>Enhanced Welcome Page</ TITLE >
</HEAD>
<BODY>
     <%
     try
     {
            String userId = session.getAttribute("userId");
     %>
     <h1>Enhanced Welcome Page</H1>
     <%
out.println("Welcome to the Web site, " + userId);
     }
     catch(Exception e)
     {
          out.println("Failure:" + e);
     }
%>
</BODY></HTML>

The tags <% and %> are special tags that tell the servlet engine (the servlet engine processes JSPs, too; you’ll see why in a moment) that this is Java code, not HTML. The session and out variables are automatically allocated and initialized in a JSP, although session could be null if, in fact, no session exists.

When it runs, this JSP obtains the user ID from the session and writes the phrase “Welcome to the Web site” followed by the user ID after a heading that says “Enhanced Welcome Page.”

Although JSPs appear to be extensions of HTML, in reality JSPs are servlets in disguise. When the Web server invokes the servlet engine and the servlet engine detects that the file name has a .jsp extension, it knows the page is a JSP. The servlet engine finds the page that contains the text above and parses it. As the engine is parsing, it converts the page into the source code of a servlet. The static HTML elements are converted to out.println() method calls containing the HTML. The Java code is simply copied into the servlet source code. It wraps the generated code with the required import statements, class definition statement, braces, and whatever else is required to create a servlet. It then compiles the servlet. If that is successful, it then executes the servlet.

Once the servlet has been successfully compiled, the parsing and compilation process will not occur again unless the JSP document has been changed. The servlet engine looks at the time stamp on the JSP and the time stamp on the compiled servlet class file to decide if it needs to recompile the JSP.

Although it is possible to design complex systems without JSPs or without servlets, many systems are designed using both servlets and JSPs. The complex business logic is coded as servlets. This logic doesn’t change often, and you would not want to clutter the presentation with its complexities. Once the business logic is executed, the servlet usually stores objects in the HttpRequest or HttpSession object and, using a RequestDispatcher, passes control to a JSP. The JSP retrieves the object and uses its values to build the display dynamically.

Although a complete discussion of JSPs is beyond the scope of this book, here are a few of the other JSP tags:

GETTING STARTED WITH SERVLETS AND JSPS

Image

If you choose to install the Tomcat Web server bundled with the CD-ROM that accompanies this book, you already have a complete environment for testing servlets and JSPs. Tomcat, the servlet engine from the Apache Project, is also integrated with Eclipse; you can actually debug your servlets from inside the Eclipse IDE.

Or, you can download Tomcat from the Apache Web site (http://tomcat.apache.org/) and install it. For this exercise, you can assume that Tomcat is installed in C:apache-tomcat. If you have installed Tomcat in some other directory, then substitute your directory in place of apache-tomcat.

Once you install Tomcat and start it, you will need to place your compiled servlet class files and JSPs in the proper directories for them to be recognized by the servlet engine. For this exercise, you will copy the compiled class file to the examples directory (C:apache-tomcatwebappsexamplesservlets).

Follow the instructions in the installation and configuration information on how to invoke your servlet or JSP. In particular, you will need to make sure that there is a JAVA_HOME environment variable that points to the location where you have the JDK installed. On most Windows systems, this means you will have to use the path Computer > Properties > Environment Variables to set a new environment variable. On Windows Vista, the path is Computer > Properties > Advanced Properties > Environment Variables. Select the option to add a new environment variable. Name the variable “JAVA_HOME,” and set the value to the location of the Java SDK (C:Progra~1Javajdk1.6.0_03). Click the OK buttons until this change is accepted.

Double-clicking on (running) the startup.bat file in the apache-tomcatin directory should now start Tomcat. If Tomcat does not start, visit the Tomcat FAQ pages at tomcat.apache.org. You can stop Tomcat by running the shutdown.bat file.

You will need to specify a port number if the servlet engine is not running on port 80. For example, invoking myjsppage.jsp if the servlet engine is running on port 8080 might require you to enter an address like this into your browser:

http://localhost:8080/myjsppage.jsp

This address references a Web server running on port 8080 on your local machine. By default, Tomcat uses port 8080, although you can change this at your convenience.

After you install Tomcat or another Web server/servlet engine, make sure the examples supplied with the servlet engine work before you proceed to the exercises.

To make sure Tomcat is installed and working properly, type this URL in your browser:

http://localhost:8080

You should see the introductory Tomcat page in your browser. Again, if you do not, check the FAQ section of the Apache Tomcat Web site.

Next, make sure the Apache servlet environment is working properly. Type this URL into your browser:

http://localhost:8080/examples/servlets/index.html

You should see a page that demonstrates several pre-packaged servlet pages.

Finally, make sure the Apache JSP environment is working properly. Type this URL into your browser:

http://localhost:8080/examples/jsp/index.html

You should see a page that demonstrates several pre-packaged JSP pages.

EXERCISES

In this example exercise, you are going to code a simple servlet that creates a session the first time it is invoked and displays a simple page. Every time you refresh the page, you are going to run the servlet and increment a counter that counts the number of times you have run the servlet and displays this result.

  1. Create a CounterServlet.java file with the editor.

  2. In order to compile a servlet, you will need to import the following packages.

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

  3. CounterServlet will extend HttpServlet to create the shell for the class, like this:

    public class CounterServlet extends HttpServlet
    {
    }

  4. Next, you need to create code for the doGet() method:

    public void doGet(HttpServletRequest req, HttpServletResponse res)
               throws IOException, ServletException
    {
    }

  5. You are now ready to code the body of the doGet() method. This will be the code that executes every time the servlet is invoked:

    public void doGet(HttpServletRequest req, HttpServletResponse res)
               throws IOException, ServletException
    {
    // You must set the content type before writing output.
         res.setContentType("text/html");
    // This creates a session if one doesn't exist or retrieves it if it does
    // exist.
         HttpSession session = req.getSession();
    // Sessions are like HashMaps and only contain objects not primitives.
         Integer count = (Integer) session.getAttribute("count");
    // Count will be null the first time you invoke the servlet because it is a
    // new session.
         if (count == null)
              count = new Integer(1);
         else
              count = new Integer(count.intValue() + 1);
    // This stores the object back into the session.
         session.setAttribute("count", count);
    // This is writing the HTML back to the browser.
         PrintWriter out = res.getWriter();

         out.println("<html>");
         out.println("<body>");
         out.println("<head>");
         out.println("<title>" + "Counter Page" + "</title>");
         out.println("</head>");
         out.println("<body>");
         out.println("<h1>Counter Page</h1><hr>");
         out.println("Welcome to the Web site<p>");
    out.println("You have been here " + count.intValue() + " time(s)<p>");
         out.println("</body>");
         out.println("</html>");
    }

  6. Compile the servlet. You will need to include the jar files that contain the servlet classes in your compile command. Do this by adding the extdirs command to the compile command.

    javac -extdirs C:apache-tomcatlib CounterServlet.java

  7. Once you have successfully compiled CounterServlet, you will need to copy the java class to the location used by the servlet engine to deploy the servlet. If you are using Tomcat, you will need to copy the class file to the servlet classes directory (C:apache-tomcatwebappsexamplesWEB-INFclasses).

    Image

    You will also need to modify the Tomcat configuration file (C:apache-tomcatwebappsexamplesWEB-INFweb.xml) and add the proper references to CounterServlet. These references tell Tomcat how to convert the names in the URL to a particular servlet. For your convenience, a modified web.xml file (suitable for the Tomcat version supplied on the CD) is provided in the Examples directory for this chapter. Copy that file to C:apachetomcatwebappsexamplesWEB-INFweb.xml. You may also need to stop, and then restart Apache so that it loads this new configuration file.

    If you are using another servlet engine, you will have to consult the documentation about how to deploy the servlet. In most cases, you can deploy a simple servlet by dropping the class file into the correct directory. If the documentation is hard to understand, just keep dropping it into different directories until you find the one that works.

    In order to invoke the servlet, you will need to start your browser and key into the address line the correct URL to connect to the servlet engine and invoke the servlet. A typical line might be something like this (although the port number may be different with your servlet engine):

    http://localhost:8080/examples/servlets/servlet/CounterServlet

  8. When the servlet runs, the result should look like this in the browser:

    Counter Page
    Welcome to the Web site
    You have been here 1 time(s)s

  9. Click Refresh several times and the number 1 should increment by 1 every time you refresh the page.

REVIEWING THE EXERCISES

Let’s review the simple servlet you’ve created. This servlet created a session the first time it was invoked and stored an integer object into the session. Every time the servlet was invoked again, the integer object was retrieved, the count was incremented, and an updated integer object was placed back into the session.

You could have created an int class variable and incremented its value every time you invoked the servlet without creating a session. The result with a single user would have been indistinguishable from the result you achieved using an integer object stored in the session. This approach would have failed to give the correct result if there were two users because it would show the combined count for both users rather than the user-specific count that the CounterServlet tracked for you.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset