Using Java Servlets

Before Netscape, when Mosaic ruled the Web and people needed a straightforward way to exchange information between client and server, the Common Gateway Interface (CGI) was born. CGI applications (usually called scripts) run on the server side. A user initiates a request via HTTP and optionally transmits information, which is handed off to the CGI script. The script processes the information and packages a reply, which the server sends to the user.

Before Netscape, when Mosaic ruled the Web and people needed a straightforward way to exchange information between client and server, the Common Gateway Interface (CGI) was born. CGI applications (usually called scripts) run on the server side. A user initiates a request via HTTP and optionally transmits information, which is handed off to the CGI script. The script processes the information and packages a reply, which the server sends to the user.

The Need for Servlets

When CGI scripts were first developed, they were often written in C or Perl. C had the advantage of speed, while Perl was cross-platform. Both, however, suffered from the overhead needed to fork a new process each time the Web server needed the CGI script. The Apache Web server mitigates that penalty with modules like mod_perl, but Sun Microsystems came up with a better alternative: the Java servlet.

Figure One: The complete cycle of a Java servlet request/respond transaction.

A servlet is just a regular Java class that implements the interface javax. servlet.Servlet as defined by the Java Servlet Specification (http://java.sun.com/products/servlet). Servlets run in a separate container, which runs a Java Virtual Machine. The JVM then executes the servlet as a thread.

A typical setup uses Apache as the Web server and Tomcat as the servlet container. Because the container is persistent, there is no overhead associated with starting a JVM for each servlet. (For more on setting up Tomcat, see the October 2001 article “Hangin’ With Tomcat” at http://www.linux-mag.com/2001-10/tomcat_01.html/.)

Further, the container can keep track of information between requests. HTTP offers no inherent means of doing this, so the Java servlet technology offers a convenient way to remember the state of a client/server session. Figure One shows the cycle of a request/response transaction: information flows from the Web client to the servlet, through the servlet container, and back.

Servlet Basics

Figure Two: SessionServlet adds and removes attributes.

A common situation well suited to Java servlets is the shopping cart. The client initiates a request, but most of the transaction processing takes place at the server, which must remember what else the client did this session. Java servlets refer to the saved session information as attributes.

Servlets typically interact with the user through standard HTML markup (just like a CGI script would), presenting a form to the user, who fills in the blanks. Under the hood, each form element (text, radio button, etc.) is given a name in the HTML form, and when the user presses the Submit button, that information is bundled up and transmitted to the Web server as a series of name/value pairs. The server then passes the request to the servlet container, which presents it as an HttpServletRequest object to the servlet. When the servlet returns outputs, it uses an HttpServlet Response object. The container presents the information to the Web server, which in turn sends it to the user.

Servlets at Work

The SessionServlet in Listing One (available at http://www.linux-mag.com/download/2002-04/Java.Matters.2002-04.tgz) demonstrates these concepts. It creates a session when it is first invoked and presents a form that allows you to add and remove attributes (see Figure Two).

Listing One: SessionServlet

1 import java.io.*;
2 import java.util.*;
3 import javax.servlet.http.*;
5 public class SessionServlet
6 extends HttpServlet {
8 protected void doGet
9 ( HttpServletRequest req,
10 HttpServletResponse resp )
11 throws IOException {
12 handleRequest( req, resp );
13 }
15 protected void doPost
16 ( HttpServletRequest req,
17 HttpServletResponse resp )
18 throws IOException {
19 handleRequest( req, resp );
20 }
22 private void handleRequest
23 ( HttpServletRequest req,
24 HttpServletResponse resp )
25 throws IOException {
26 HttpSession session = req.getSession();
27 processRequest(req, session);
28 resp.setContentType(“text/html”);
29 PrintWriter out = resp.getWriter();
30 out.println(“<html><body>”);
31 out.println(“<h1>Session Servlet</h1>”);
32 outputForm(out);
33 out.println(“<hr>”);
34 outputSession(out, session);
35 out.println(“</body></html>”);
36 }
38 private void processRequest
39 ( HttpServletRequest req,
40 HttpSession session ) {
41 String name = req.getParameter(“InputName”);
42 String value = req.getParameter(“InputValue”);
43 if ( req.getParameter(“AddButton”) != null )
44 session.setAttribute( name, value );
45 else if (req.getParameter(“RemoveButton”) != null)
46 session.removeAttribute( name );
47 }
49 private void outputForm( PrintWriter out )
50 throws IOException {
51 out.println(“<form action=SessionServlet method=post>”);
52 out.println(“Name: <input type=text length=20 name=InputName><br>”);
53 out.println(“Value: <input type=text length=40 name=InputValue><br>”);
54 out.println(“<input type=submit name=AddButton value=add>”);
55 out.println(“<input type=submit name=RemoveButton value=remove>”);
56 out.println(“</form>”);
57 }
59 private void outputSession(PrintWriter out, HttpSession session)
60 throws IOException {
61 out.println(“Current attributes:<p>”);
62 Enumeration enum = session.getAttributeNames();
63 while (enum.hasMoreElements()) {
64 String name = (String) enum.nextElement();
65 Object value = session.getAttribute(name);
66 out.println(name+” = “+value+”<br>”);
67 }
68 }
69 }

To add an attribute, type a name to identify it and a value in the corresponding box and click the “add” button. To remove an attribute, type its name and click the “remove” button. Each time the screen is refreshed the servlet displays all the attributes currently stored in the session. If you visit another address and browse the servlet again later, you will see that the session is still active and the attributes are still there.

The SessionServlet inner working is pretty straightforward. In order to handle HTTP requests, all you need to do is extend the class javax.servlet.http. HttpServlet and override the appropriate methods, listed in Table One.

Table One: Important HttpServlet Methods

doGet(HttpServletRequest, Called by the servlet container so that the
HttpServletResponse) servlet can handle HTTP GET requests
directed to it
doPost(HttpServletRequest, Called by the servlet container so that the
HttpServletResponse)servlet can handle HTTP POST requests directed to it

The methods doGet (lines 8 through 13) and doPost (lines 15 through 20) receive objects that represent both the request and the response. In this way, they actually perform the work of SessionServlet.

The request is handled by the method handleRequest(), which is called by both the doGet() and doPost() methods. This kind of arrangement is common practice, since it allows the servlet to transparently handle both GET and POST HTTP requests.

The first thing handleRequest() does is get the current session using the method getSession() of the request received (line 26). A new session is created by getsession() if this is the first time the servlet has been called by the client.

The method getSession() of the HttpServletRequest interface creates and returns an HttpSession object where you can store any attributes between requests. The methods associated with the HttpSession object are listed in Table Two.

Table Two: HttpSession API

session.getAttribute(String) Returns the object saved in this session with a given name
session.getAttributeNames() Returns an Enumeration of the names of all stored objects
session.removeAttribute(String) Removes the object saved with a given name from this session
session.setAttribute(String,Object)Saves the given object to this ses-sion, associating it with a name

Once created, the HttpSession object is associated with all requests from the same client to the same Web application (and can be retrieved using the same get Session() method), until it is destroyed. All the low-level details are managed by the servlet container.

The method processRequest() is called in line 27 to actually process the request. All data from the form are made available to the servlet through the appropriate API, which provides several convenient methods to get the request’s parameters. These are shown in Table Three. Once parameters are received, the servlet processes them and can optionally store them as session attributes. It can also retrieve attributes that have already been stored from previous requests in the session.

Table Three: Getting Parameters From the HttpServletRequest

request .getParameter(String) Returns the value of a parameter, given its name
request .getParameterMap() Returns a map of all parameters of the request; the keys are the parameter names and the values are the parameter values, represented as a String array
request .getParameterNames() Returns the names of all parameters of the request, as an Enumeration
request.getParameterValues(String)Returns a string array containing all values of a given parameter

The processRequest() method gets the text typed into the form fields (InputName and InputValue) in lines 41 and 42, and the name of the button clicked (RemoveButton or AddButton). It then adds or removes the attribute in lines 43 through 46.

Once processing is complete, the information is presented through the interface HttpServletResponse (see Table Four). There are methods to set the headers and body of the response, send back errors or redirect the request. In order to send back a normal response, all you need to do is set the MIME type, get a suitable character or binary stream and write the data.

Table Four: Sending an HttpServletResponse

response .getOutputStream Obtains a stream for writing binary data
response .getWriter Obtains a stream for writing text data
response .setContentTypeSets the MIME type of the response

You set the MIME type of the response you are sending back with the setContentType method. The most common case is “text/html” when you are returning an HTML page, but setting the MIME type and using the appropriate stream lets you return any type of data.

In line 28, the handleRequest() method sets the content type of the response to text/html. It gets a text stream in line 29 and outputs the actual page in lines 30 through 35, with the help from both the outputForm() and outputSession() methods.

The method outputForm() in lines 49 through 57 outputs the form used to interact with the user. This is where parameters are named InputName and InputValue. The associated values will be those filled in by the user. The method outputSession() in lines 59 through 68 outputs all attributes currently stored in the session. In line 62, the getAttributeNames() method of the session is used to iterate over all attributes.

After It’s Written

All servlets must be part of a Web application as defined by the Servlet Specification. This includes a set of HTML pages, servlets, JSP pages, classes, and other resources. These conform to a certain directory structure and require a special file, web.xml, which configures security constraints, initial parameters, and the like. Tomcat requires that the web.xml file exist, but if the file provides no parameters, Tomcat uses default values.

In order to get our ServletSession example running under Tomcat, follow the steps below.

1. Compile the example:

  • save the code to a file named ServletSession.java

  • add the file $CATALINA_HOME/common/lib/servlet.jar to your Java classpath

  • compile the source file ( javac ServletSession.java )

2. Deploy it into Tomcat:

  • create the directory $CATALINA_ HOME/Webapps/staging/WEB-INF/classes

  • create a default web.xml file in $CATALINA_HOME/Webapps/staging/WEB-INF (see Listing Two, also available online)

  • copy to the directory $CATALINA_ HOME/Webapps/staging/WEB- INF/classes the compiled servlet ( Session Servlet.class)

  • restart Tomcat

Once the servlet is deployed, you can see it in action by browsing the address http://localhost:8080/staging/servlet/SessionServlet/.

Exploring Further

Java servlets are natural replacements for CGI applications. They are easier to develop and offer better performance. Servlets are a good choice when your application has moderate to complex logic or when you need to return data other than HTML pages, especially binary data.

The disadvantage of Java Servlets is that they don’t provide, by default, a good separation of program logic and presentation, since statements that output HTML are intermixed with the application logic, making maintenance difficult. One solution to that problem is the Velocity template engine, a Jakarta project (http://jakarta.apache.org/velocity).

There’s a wealth of information available for your next steps. A good starting point is the documentation that comes with Tomcat, which shows you how to develop, organize, and deploy Web applications.

Alexandre Calsavara is a technical writer working with embedded systems, C, C++, and Java. He can be reached at apcal@mail.com.

Comments are closed.