Chapter 23: Servlets

23.1: Html Form

Forms are used to make an interactive Html web page. One form may contain several form elements, such as checkboxes, radio buttons, text fields, text areas, drop-down/scrolling selects, etc. Each element is used to send to the server a parameter with a name and value. The name of the parameter is simply assigned in the tag, and the value is determined by the user's interact with the element.

When the form is posted (e.g. by clicking the "Submit" button), all relevant parameters in this form will be posted to the web server. The server can then respond to the values of these parameters.

Some basic form element's tags are listed below:

   <INPUT  TYPE=RADIO  NAME=Animal  VALUE=dog>

If you assign the same name to a group of such RADIO elements, then they belong to the same group with one single parameter.

   <INPUT  TYPE=CHECKBOX  NAME=Horse>

If the checkbox is checked, when the form is posted, the parameter list posted will include this parameter, and its value will be string "on". If it is not checked, the parameter list posted will simply not include this parameter.

   <INPUT  TYPE=TEXT  NAME=Name  VALUE="Your  NAME"  SIZE="40" >
   <INPUT  TYPE=TEXT  NAME=Name  VALUE="Your  NAME"  MAXLENGTH="40">

The value will appear in the text field as a default value. SIZE or MAXLENGTH both mean the number of characters that this text field can hold.

   <TEXTAREA  NAME=Name  COLS=40  ROWS=10  WRAP=SOFT>Comment...</TEXTAREA>

COLS is the number of characters in a line, and ROWS is the number of rows. WRAP can be OFF, HARD, or SOFT. When it is OFF, there is no text wrap. When it is SOFT, only text wrap visually but no wrap in the posted data. If its HARD, the line wrap will be posted.

   <INPUT  TYPE=PASSWORD  NAME=Password  VALUE="123ABC">

The content in the text field will be displayed as "*".

   <INPUT TYPE=FILE  NAME=FileLocation   ACCEPT=image/*>

This will display a text field and a "Browse" button. Clicking this button will bring out a OS dialog allowing you to browse through your computer and select a file. When submitted, the full path of this selected file will be sent as the parameter value, e.g. "c:\mydocument\index.Html".

   <INPUT TYPE=HIDDEN  NAME=HiddenParameter  VALUE="Hidden value">

This element will not be displayed by the browser and thus hidden from the client.

   <SELECT  NAME=Myselect1  SIZE=2  MULTIPLE>
   <OPTION VALUE=Value1>Displayed1</OPTION>
   <OPTION VALUE=Value2>Displayed2</OPTION>
   <OPTION VALUE=Value3>Displayed3</OPTION>
   </SELECT> <BR>

Without SIZE, it is a drop-down select. With SIZE, it is a scrolling select, and SIZE defines the number of items shown. When it is a scrolling select, you can also put MULTIPLE to allow multiple selection. In this case, the posted data will contain more than one parameter with the same name.

   <INPUT TYPE=IMAGE  NAME=ImageSubmit  SRC="car.jpg"  BORDER="0">

Use a image as a submit button.

   <INPUT  TYPE=SUBMIT  NAME=Submit1 VALUE=Submit1>

This element appears to be a button with a label of the specified value. When it is clicked, all the relevant parameters of this form will be posted to the web server. If this element has a name and value, its own parameter will also be sent.

   <INPUT  TYPE=RESET VALUE=Reset>

Appears to be a button.

The following is a Html page with a form containing above elements, and a Java servlet to return a Html page displaying the posted parameters:

   
   ***************************************************************************
   
   <TITLE> A testing page for Html FORMs</TITLE>
   <HEAD>
   
   <BODY>
   
   <FORM METHOD=post action="http://localhost/servlet/Test">
   <PRE>
   
   Dog     <INPUT TYPE=radio NAME=Animal VALUE=dog> <BR>
   Cat     <INPUT TYPE=radio NAME=Animal VALUE=cat> <BR><BR>
   Horse   <INPUT TYPE=checkbox NAME=Horse> <BR><BR>
   Opinion <TEXTAREA NAME=Opinion COLS=40 ROWS=10 WRAP=SOFT>Comment...</TEXTAREA> <BR><BR>
   Name    <INPUT TYPE=TEXT NAME=Name VALUE="Your name" SIZE="20" MAXLENGTH="20"> <BR>
   Passwd  <INPUT TYPE=PASSWORD NAME=password VALUE="123ABC"> <BR>
   File    <INPUT TYPE=FILE NAME=FileLocation ACCEPT=image/*> <BR>
   Hidden  <INPUT TYPE=HIDDEN NAME=HiddenParameter VALUE="Hidden value"> <BR>
   Drop-down <SELECT NAME=Myselect1>
   <OPTION VALUE=Value1>Displayed1</OPTION>
   <OPTION VALUE=Value2>Displayed2</OPTION>
   <OPTION VALUE=Value3>Displayed3</OPTION>
   </SELECT> <BR>
   
   Scroll list <SELECT NAME=Myselect2 SIZE=2 MULTIPLE>
   <OPTION VALUE=Value1>Displayed1</OPTION>
   <OPTION VALUE=Value2>Displayed2</OPTION>
   <OPTION VALUE=Value3>Displayed3</OPTION>
   </SELECT> <BR><BR>
   
   <INPUT TYPE=IMAGE NAME=ImageSubmit SRC="car.jpg" BORDER="0"> <BR><BR>
   <INPUT TYPE=SUBMIT NAME=Submit1 VALUE=submit1> <BR>
   <INPUT TYPE=SUBMIT NAME=Submit2 VALUE=submit2> <BR>
   <INPUT TYPE=RESET VALUE=reset:-)>
   
   </PRE>
   </FORM>
   </BODY>
   </Html>
   
   *****************************************************************************************
   
   import java.io.*;
   import javax.servlet.*;
   import javax.servlet.http.*;
   import java.util.*;
   
   public class Test extends HttpServlet {
   
       public void doPost(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException
       {
           Enumeration e = request. getParameterNames();
           String name = null, value = null;
   
           response. setContentType("text/Html");
           PrintWriter responseWriter = response. getWriter();
           StringBuffer sb = new StringBuffer();
           sb.append("<Html><title>Hello! Your buttons:</title>" +
                     "<body><p><strong>The start of button testing page." + 
                     "</strong></p> <p></p> <pre>");
   
           sb.append("Specially, checkbox Horse = " + 
                     request. getParameter("Horse") + "<br><br>");
   
           while(e. hasMoreElements())
           {
               name = (String)e. nextElement();
               value = request. getParameter(name);
               sb. append("Parameter " + name + " = " + value + "<br>");
           }
   
           sb. append("</pre><p></p><p><strong>End</strong></p></body></Html>");
   
           responseWriter.println(sb. toString());
           responseWriter.flush();
           responseWriter.close();
       }
   }

23.2: Why Servlet

Servlets are used to replace CGI programs. With CGI, every time a CGI program is invoked it will be started as a new process, and when the communication ends, this process terminates. Therefore, if a CGI program is invoked many times, OS will start the same process many times. If there are many CGI programs being invoked meantime, there will be many processes run by the OS.

Java servlets are run as threads. A separate thread has smaller memory footprint than a separate process.

Moreover, once a servlet is first-time invoked, it can stay in the memory. Next time it is invoked again, only it's service method is called again. This saves the overhead of starting and terminating a process, including creating and deleting objects, setting up and disconnecting database connections, etc.

Therefore, if the task to be performed is not big (CGI programs which is normally written in C, C++ or Perl run faster than Java programs), servlets are better off than CGI programs.

Servlets are effective for

  1. Developing web-based solutions that help provide secure access to a web site;
  2. Interact with database;
  3. Dynamically generate custom HTML documents;
  4. Session tracking

With servlets, clients no longer need to directly access the server database. They only need to connect to the server with standard protocols and servlets can deal with the database. Such clients are called thin clients.

23.3: Interface Servlet

Interface javax.servlet.Servlet provides some methods to interact with web server:

When the web server loads in the servlet, before it is used, the server will generate a ServletConfig object and pass it to this method to initialize the servlet. ServletConfig contains the initialization parameters for the servlet and a ServletContext object which provides the servlet with the access to the environment, i.e. the server in which its is running.

When the web server needs to invoke the servlet to respond to a client request, it will generate a ServletReqeust and ServletResponse object from the client request (directly or indirectly from the Socket connection with the client), which represents the characteristics of the client request and the response to the client respectively, and pass it to the servlet's service method. The servlet will then get all the information from the ServletReqeust, do what is required to do, then write the response through the ServletResponse.

When the web server no longer needs a servlet in the memory, it will call this method to deallocate all its resources.

23.4: Class HttpServlet

Class javax.servlet.http.HttpServlet implements interface Servlet. Its service method receives two arguments HttpServletRequest and HttpServletResponse. Internally it calls HttpServletRequest's method getMethod to determine the method type of the client request - GET or POST or else, then pass the HttpServletRequest and HttpServletResponse object to HttpServlet's corresponding methods such as doGet, doPost etc..

23.5: Interface HttpServletRequest

Interface javax.servlet.http.HttpServletRequest extends javax.servlet.ServletRequest. Main methods:

Returns the value of a parameter for its name, stored by the web server in the HttpServletRequest object, representing the characteristics of the client request.

Returns an enumeration of names of all the parameters stored in the HttpServletRequest object.

Returns an array of the values of the parameters. Cookies are used for session tracking.

Returns an array of Cookie objects stored on the client by the server.

Returns a HttpSession object associated with the client's current browsing session. If the boolean argument is true, a new HttpSession object will be created for the client if the client does not have one.

23.6: Interface HttpServletResponse

Interface javax.servlet.http.HttpServletResponse extends javax.servlet.ServletResponse. Main methods:

Add one cookie to the header response to the client. The cookie's age and whether the client accepts cookies will determine whether the cookie will be stored on the client.

Returns a byte-stream output stream.

Returns a character-stream output stream.

Specifies the MIME type of the response to the client browser. E.g. "text/html".

23.7: Session Tracking with URL Rewritting

When a Html page containing the following Http form is sent to the client browser:

   
   <form method=get action="/servlet/DynamicHome/SessionId12345">
   <input type=submit value="Continue">
   </form>

The request line will be

   
   GET servlet/DynamicHome/SessionId12345 HTTP/1.0

The HttpServletRequest object created by the web server for this client connection will contain a pathInfo field of "servlet/DynamicHome/SessionId12345", which can be returned by its method getPathInfo. The first token separated by delimitor "/" is "servlet", which indicates that the following token is the name of a servlet. The last token is a session ID previously sent by the web server (by a servlet).

This is the way of session tracking through URL rewriting. If you want to track a customer within this session, you send him a Html page with some identification information written at the end of the URL of the Html form. Then this identification information will be sent back by the client browser.

This session tracking technique can not keep track of clients between different sessions - i.e. if the customer turns of his computer and later reconnect to the server, the URL rewritten information will be gone.

23.8: Session Tracking with Hidden Forms

Session tracking with hidden forms is very straight forward. A hidden form is a form element with a normal form which is not displayed on the client browser. The only use of a hidden form is that its parameter will be sent back to the server with a Http POST method once the "Submit" button in that form is pressed:

   
   <form method=post action="/servlet/CheckStock">
   <pre>
   Your name     <input type=text name="Name"   size="20" maxlength="20"> <br>
   Street        <input type=text name="Street" size="20" maxlength="20"> <br>
   Suburb        <input type=text name="Suburb" size="20" maxlength="20"> <br>
   <input type=hidden  name="SessionId"  value="123456">
   <input type=submit value="Continue">
   </pre>
   </form>

Therefore, if you want to keep track of a client within a session, you can insert one or many hidden forms in the Html page sent to him. The parameters and their values of those hidden forms will be sent back with Http POST method together with other parameters such as the name, street and suburb:

   
   Name=Frank+Liu&Street=6%2F11+Adelaide+St&Suburb=Murrumbeena&SessionId=123456

You can get it with HttpServletRequest's method getParameter:

   
   String sessionId = request.getParameter("SessionId");

Just like URL rewriting, this session tracking technique can not keep track of clients between different sessions.

23.9: Session Tracking with Cookies

The above-discussed session tracking techniques has two limitations:

  1. Http protocol or the server program (such as ServletRequest and ServletResponse) does not provide any support
  2. The tracking of the client can not be done between different sessions

To solve these two problems, Http protocol provides support for cookies.

When a servlet or CGI program identifies a new client whom it wants to track, it may add one or more headers to its response. Each of these cookie headers contains basically a pair of Strings: a parameter name and value. There may be other optional attributes attached after this String pair, used to instruct the client browser how to deal with these cookies.

The client browser will store these cookies in a file on the hard disk. So session tracking with cookies is effective even after the client browser is turned off. Before the browser connects to any server, it will check the cookie file first. If it finds some cookies previously sent from the same URL and path, it will send back these cookies to the server.

A browser is expected to store at least 300 cookies in total, a maximum of 20 cookies for each specific path and site. Each cookie is up to 4KB.

* Sending a cookie to the client

To send a cookie to a client, include the following header in the response:

   
   Set-Cookie: name=value; expires=date;
   path=pathname; domain=domain-name; secure

Only the name/value pair is a must. Other attributes are optional. They are not used by the server to store information in the client side, but used by the server to instruct the client browser how to deal with the cookie:

Specifies the date of expire of that cookie. Only GMT is used, such as "Wednesday, 01-Sep-96 00:00:00 GMT". If no expire date is secified, the cookie is only valid for the current session.

The path and domain attributes specify a location range. When the browser is trying to connect to any server within this range, the cookie will be sent. Suppose the path is "/pub", then its subdirectories such as "/pub/images" is also valid. No path attribues means that the cookie is valid only for the originating path and site. A path of "/" means that all paths from the originating site are valid.

This attribute specifies a domian range. It should contain at least two dots, e.g. ".ibm.com". Sub-domains such as ".software.ibm.com" is also valid.

This attribute tells the client to return the cookie only over a secure connection (via SHTTP and SSL). Leaving out this attribute means that the cookie is always returned.

Therefore, when the brower returns the cookies to the server, only the name/value pair will be sent back.

* Returning a cookie to the server

The cookie header sent by the browser to the server looks like:

   
   Cookie: name1=value1; name2=value2; name3=value3; ...

Suppose there are two headers set by the following headers:

   
   Set-Cookie: Suburb=Caufield; path=/;
   Set-Cookie: Suburb=Murrumbeena; path=/pub;

When the browser connects to path "/pub", the two cookies are both valid. The cookie with the most specific path will be sent first:

   
   Cookie: Suburb=Murrumbeena; Suburb=Caufield;

* Java's support for Cookies

To make convenient the passing of cookie information between classes, Java provides class javax.servlet.http.Cookie. It is a class simply containing the cookie attributes and some set and get methods.

When HttpServletRequest is created, it will read in all the cookie headers sent by the client and create from them Cookie objects by using Cookie's set methods. Servlets can call its method getCookies to get all cookies in an array.

HttpServletResponse provides a method addCookie for the servlet to add one new cookie each time to the response to the client. It will use Cookie's get methods to acquire all the cookie attributes and write them into the response in the correct Http format discussed above.

When sending cookies to the client:

   
   public void doPost(HttpServletRequest request, HttpServletResponse response)
   {
       ...
       Cookie c1 = new Cookie("ID", "123456");
       c1.setMaxAge(1200);        // number of seconds
       response.addCookie(c1);
   
       Cookie c2 = new Cookie("OrderedCar", "Corola CSX");
       c2.setMaxAge(1200);
       response.addCookie(c2);
   
       PrintWriter = response.getWriter();     // must after addCookie
       ...
   }

When retrieving cookies from the client:

   
   public void doGet(HttpServletRequest request, HttpServletResponse response)
   {
       ...
       Cookie [] cookies = request.getCookies();
   
       for (int i = 0; i < cookies.length; i++)
       {
           System.out.println("Cookie name = " + cookies[i].getName()
                              + ", value = " + cookies[i].getValue());
       }
       ...
   }