Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

Servlets, Session Tracking Using URL Rewriting

Java Programming, Lecture Notes # 692, Revised 3/16/99.

Preface

Introduction

Sample Program

Interesting Code Fragments

Program Listing


Preface

Students in Prof. Baldwin's Advanced Java Programming classes at ACC will be responsible for knowing and understanding all of the material in this lesson beginning with the spring semester of 1999.

This lesson was originally written on March 16, 1999.

The sample servlet in this lesson was tested using Win95, the JDK 1.2 download package from JavaSoft, the JSDK 2.0 download package from JavaSoft, and the servletrunner program that is included in the JSDK. The sample program was tested using servletrunner both from the same machine, and from a different machine on the network.

Introduction

This and the next several lessons will show you some of the ways to implement session tracking using servlets.

An earlier lesson showed you how to implement session tracking using hidden fields on the HTML form. This lesson illustrates a similar approach using URL rewriting. Other approaches will be illustrated in subsequent lessons.

If you observed the URL window in your browser while running the program named Servlet07 from an earlier lesson, you probably noticed that after several cycles, the window contained something like the following.

http://baldwin:8080/servlet/Servlet07?
firstName=harry&
item=tom&
item=dick

What you are seeing here is the standard way in which HTML forms pass parameters to their HTTP servers. (Manual line breaks were inserted to force the material to fit on the page.)

When the user clicks on the submit button, a string containing the names and values for all of the fields is created and concatenated onto the URL. The string of parameter values is joined to the URL with a "?" character. The individual parameters are separated from one another with the "&" character.

Recall that in Servlet07, the field named firstName was the visible field in which the user entered a name. The fields named item were hidden fields that were created and populated with historical data when the servlet generated the HTML form for return to the client.

It doesn't really matter how these parameter names and values come to be concatenated onto the URL. As far as the servlet is concerned, their values are accessible using the methods getParameter() and getParameterValues().

This suggests that in some cases, it might be beneficial for the servlet to save the historical data by concatenating it onto a URL referenced in the HTML page before returning the page to the client. That is one of the ways that URL rewriting can be used to implement session tracking.

Sample Program

This sample program is designed to illustrate the concept of URL rewriting and is not intended to have any particular value in its own right.

Servlet08.java illustrates session tracking using URL rewriting. In this case, parameters containing the historical data are added to the servlet's URL each time the servlet generates a new HTML page.

Each time the servlet is invoked, it creates and displays an HTML page on the client screen. The page displays:

Each time the user clicks on the hyperlink, the client sends a GET request to the server. The GET request invokes the servlet, which determines the current date and time. An HTML page is created and sent back to the client.

The current date and time in milliseconds is added as a parameter named item to the servlet URL referenced by the hyperlink in the newly-created HTML page. In addition to the current date and time, the values of the previous dates and times when the user invoked the servlet by clicking the hyperlink are retrieved from the incoming URL and appended to the new URL.

In other words, the parameter values for each successive URL that is generated match those of the previous URL. In addition, a new parameter value is added which represents the current date and time.

The historical data is saved by embedding it in the new HTML page that is returned to the client. There is no requirement to save the historical data in a database or in the server's file system.

This approach places no special requirements on the server software and should be compatible with all browsers that support hyperlinks.

A typical screen output produced by running this program through several cycles during a single session is shown below.

Click Here

Your list of times is:

16-Mar-99 9:35:52 PM

16-Mar-99 9:58:03 PM

16-Mar-99 9:58:05 PM

16-Mar-99 9:58:06 PM

16-Mar-99 9:58:08 PM

The URL that produced this output is shown below with manual line breaks inserted to force it to fit on the page.

http://baldwin:8080/servlet/Servlet08?
item=921641752080&
item=921643083420&
item=921643085620&
item=921643086990

 

Interesting Code Fragments

The first fragment shows the beginning of the controlling class and the beginning of the doGet() method. You have seen this before, so I won't discuss it further.

public class Servlet08 extends HttpServlet{
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res)
                      throws ServletException, IOException{

An HTTP URL can have multiple parameters with the same name. In this case, the parameters are all named item. The next fragment gets the values stored in all of the parameters named item and saves them in a String array named items.

The fragment also instantiates and initializes a String object used later to construct a new parameter string for the URL.

    String parameters = "?";
    
    String[] items = req.getParameterValues("item");

The next fragment uses the parameter values from the old parameter string to construct a new parameter string. The new parameter string will later be concatenated to the URL for the servlet.

    if(items != null){
      for(int i = 0; i < items.length; i++){
        parameters = parameters + "item=" + items[i] + "&";
      }//end for loop
    }//end if

The next fragment gets the current date and time in milliseconds and saves it in a long variable named theDate. Then it concatenates the current date and time in milliseconds onto the new parameter string constructed above.

    long theDate = new Date().getTime();
    parameters = parameters + "item=" + theDate;

The next fragment begins the creation of the output HTML page. You have seen code like this many times before, so I won't discuss it further at this point.

    //Establish the type of output
    res.setContentType("text/html");
    
    //Get an output stream
    PrintWriter out = res.getWriter();
    
    //Construct an HTML form and send it back to the client
    out.println("<HTML>");
    out.println("<HEAD><TITLE>Servlet08</TITLE></HEAD>");
    out.println("<BODY>");

The next fragment constructs the hyperlink containing the URL for the servlet. Note that the hyperlink references a URL that includes the parameter string constructed above.

If you compile and run this servlet, you will need to substitute the name of your server machine or localhost in place of baldwin in this statement. baldwin is the name of my server machine.

    out.println("<A HREF=\"http://baldwin:8080/servlet/"
         + "Servlet08" + parameters + "\">Click Here</A>");

The next fragment simply provides a line of introductory text for the list of dates and times to be displayed on the screen.

    out.println("<BR><BR>Your list of times is:<BR>");    

An earlier fragment retrieved all of the data in the incoming URL parameters and saved that data in a String array named items.

If that array contains data, the next fragment displays the date and time for each element in the array.

The parameter values in milliseconds are first converted from String to long. Each of the long values is then used to instantiate a new Date object, which is displayed in the format shown earlier.

    if(items != null){
      for(int i = 0; i < items.length; i++){
        long millis = Long.parseLong(items[i]);
        Date aDate = new Date(millis);
        out.println(DateFormat.getDateTimeInstance().
                                   format(aDate) + "<BR>");
      }//end for loop
    }//end if

An earlier fragment also obtained the current date and time and saved it in milliseconds. As above, this representation of the date and time is used to instantiate a new Date object that is formatted and displayed at the end of the list on the HTML page.

    Date aDate = new Date(theDate);
    out.println(DateFormat.getDateTimeInstance().
                                   format(aDate) + "<BR>");

The remainder of the code is typical of what you have seen before and can be viewed in the complete listing of the servlet in the next section.

Program Listing

A complete listing of the program follows.

/*File Servlet08.java, Copyright 1999, R.G.Baldwin
Rev 3/16/99

The purpose of this program is to illustrate session
tracking through the use of rewritten URLs

Each time the servlet is activated, it creates an HTML
file and sends it back to the client.  The HTML file
displays an HTML hyperlink on the client screen. 

In addition, it displays a list of date/time values 
representing the dates and times at which the servlet was 
accessed from that page by clicking on that hyperlink.

Each time the user clicks the hyperlink,the servlet is 
activated, causing it create and send a new HTML page
to the client.
  
Each time the HTML page is created and sent to the
client, the URL of the servlet referenced by the hyperlink
is modified to include the current date and time plus the
date and time of each previous access made by clicking
on the hyperlink.  The date/time information is converted
to milliseconds and appended to the URL in the form of
standard URL parameters.  Thus, the length of the URL
increases each time the HTML form is created.

The servlet illustrates how it is possible to store
historical data in the parameter string that can be
appended to a URL.
 
The servlet was tested using the JDK 1.2 download package
from JavaSoft along with the Java Servlet Development Kit
(JSDK) 2.0 from JavaSoft. All tests were performed 
under Win95.

The servlet was tested using the servletrunner program that
is included in the JSDK with the servletrunner program 
running on the same machine and also with the servletrunner
program running on a different machine on the network. 


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

public class Servlet08 extends HttpServlet{
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res)
                      throws ServletException, IOException{

    //Ref variable used to construct the parameter string
    String parameters = "?";
    
    //An array for getting and saving the values contained
    // in the parameters named item.
    String[] items = req.getParameterValues("item");
    
    if(items != null){
      for(int i = 0; i < items.length; i++){
        //Access the old parameter string to construct the
        // new parameter string to append to the URL below.
        parameters = parameters + "item=" + items[i] + "&";
      }//end for loop
    }//end if

    //Get the current date and time in milliseconds. Add 
    // the current date and time to the parameter string
    // constructed above.
    long theDate = new Date().getTime();
    parameters = parameters + "item=" + theDate;

    //Establish the type of output
    res.setContentType("text/html");
    
    //Get an output stream
    PrintWriter out = res.getWriter();
    
    //Construct an HTML form and send it back to the client
    out.println("<HTML>");
    out.println("<HEAD><TITLE>Servlet08</TITLE></HEAD>");
    out.println("<BODY>");

    //Construct the hyperlink referencing the servlet here.
    // Note that the hyperlink references a URL that 
    // includes the parameter string constructed above.
            
    //Substitute the name of your server or localhost in
    // place of baldwin in the following statement.
    out.println("<A HREF=\"http://baldwin:8080/servlet/"
         + "Servlet08" + parameters + "\">Click Here</A>");

//Display the historical data stored in the parameter
    // string.
    out.println("<BR><BR>Your list of times is:<BR>");   

    if(items != null){
      for(int i = 0; i < items.length; i++){
        long millis = Long.parseLong(items[i]);
        //Convert from milliseconds as a String to a Date
        // object.  Then format for display.
        Date aDate = new Date(millis);
        out.println(DateFormat.getDateTimeInstance().
                                   format(aDate) + "<BR>");
      }//end for loop
    }//end if

    //Convert from milliseconds to a Date object and then
    // format for display.
    Date aDate = new Date(theDate);
    out.println(DateFormat.getDateTimeInstance().
                                   format(aDate) + "<BR>");

    out.println("</BODY></HTML>");//finish HTML page
      
  }//end doGet()
}//end class Servlet08

-end-