Sun Java Solaris Communities My SDN Account
 
Article

JavaServer Technologies, Part II

 
 

Articles Index

Technologies, Part II

There are several reasons why programmers resort to CGI scripts when designing web servers. The first is to provide dynamic content--content that may be different each time a client browser accesses a page. Examples include digital clocks that always display the current time of day, or counters that display messages like "You are visitor number 10,039 at this site."
 
Another reason for resorting to CGI scripts is to write special server applications that give trusted users the ability to read and write data to the server disk by issuing commands from a client application. For example, the Java File Server (JFS) illustrates a classic remote service allowing users to read and write to the server itself. JFS provides print and files services to Java applets much like the UNIX Network File Server, NFS.
 
JavaServer technology is well suited to these kinds of applications and generally simplifies the problem by letting you write all server and client code in Java. Without a JavaServer, you have to write CGI (Common Gateway Interface) programs--most commonly in Perl, Shell scripts, or C--to allow client applications a way to work around the built-in security features that protect both servers and clients from unwanted modifications to local files and resources.
 

Servers and Servlets

Keep in mind the distinction between a JavaServer and a servlet. As mentioned in the previous article, a servlet is the server-side equivalent of an applet. Applets add dynamic behavior to client browsers. Servlets add dynamic behavior to servers. This article will only touch lightly on server administration and will focus primarily on the advantages of extending server functionality with servlets.
 
At the most basic level, a JavaServer lets you administer a web site exactly as you would if you were using an Apache server, an NCSA server, a CERN server, or any of the Netscape family of servers (Netsite Communications Server and Netsite Commerce Server). The JavaServer has the advantage of allowing the same servlet extensions to run on a Windows platform as well as a UNIX platform. A JavaServer can therefore be used in place of a Microsoft Internet Information Server running on Windows NT.
 
For those familiar with CGI programming, servlets do for a JavaServer what CGI scripts do for the above mentioned servers--or what WinCGI (with Visual Basic, Delphi, or Visual C++) does in the case of the Microsoft server on Windows NT.
 
Developing servlets is a three-step process:
  1. Write the servlet
  2. Install the servlet
  3. Run the servlet

 
Before digging into the the topic of developing servlets, you should be familiar with the kinds of CGI scripts servlets are intended to replace.

Extending a JavaServer with CGI Scripts


 
If you're already familiar with HTML forms processing with CGI scripts, you can skip this section. But first, you may want to read the HTML code used to generate the form shown in Figure 1. This form is processed by the CGI Perl script, jdc-example01.pl The next section will show how the same form is handled using a servlet extension instead of a CGI extension to the server. The main things you need to understand before moving on to the next section include the difference between CGI GET and POST methods for submitting forms, and the manner in which form parameters or names are passed from the HTML form to a CGI script.
 
First consider how traditional CGI Perl scripts are handled by a JavaServer. There won't be any surprises here for those accustomed to extending server functionality by writing CGI scripts, whether in Perl, UNIX shell script, AWK, C, or Visual Basic. However, it is important to be clear about how name-value parameters are defined within an HTML form, and how they are passed to CGI scripts by the server. You'll see the same concepts applied to servlets when they are introduced in a later section.
 
This section is written from the perspective of conventional CGI programming. For those unfamiliar with CGI programming for extending the services of a web server, this should acquaint you with the basics. If you already build or maintain servers, the code here should be easy to understand and will demonstrate that a JavaServer provides the same services as Apache, NCSA, CERN, Netscape, Microsoft, Internet Information Server, and other common web servers.
 
You must build two server-side pieces to solve the problem of form submission requests and responses. Like many programming problems the matter breaks down into input and output. In CGI terminology that's the HTTP request and the HTTP response. The HTML page containing the form makes up the input request to be submitted to the server when the user presses the submit button appearing on the form. The CGI script reads the input data as key-value pairs or name-value pairs, processes the data, and generates an output response that the server passes back to the client browser that submitted the form.
 
Consider the form in Figure 1.
example01
Figure 01.Full Size


The HTML code that generates this form is simple:
<html>
<head>
 <title>JDC Registration Page</title>
  </head>
  <body>
  <h1>JDC Registration Page</h1>

 <form method="GET" action="cgi-bin/jdc-example01.pl">
        <pre>
   First Name: <input type="text" name="firstname">
   Last Name:  <input type="text" name="lastname">

    <input type="submit">    <input type="reset">
     </pre>
    </form>
  </body>
</html>


File: server_root/public_html/jdc-example01.html Source




 


Figure 2. Dynamic Page Generated by Perl Script. Full Size


See Perl Script: server_root/cgi-bin/ jdc-example01-simplified.pl
 
Note: The HTML, Perl, and Java files used in this article are not distributed with JavaServer. If you wish to use these programs with a JavaServer, you must copy them to the appropriate directory relative to the root directory where your JavaServer is installed. For convenience partial pathnames, relative to the server_root directory have been specified so you will know where to put them. Copy HTML files to server_root/public_html. Copy Perl CGI scripts to server_root/cgi-bin. Copy Java source files to server_root/servlets. Actually, this is not strictly necessary in the case of Java files. Only the compiled .class file needs to be copied to server_root/servlets.
 
The above form specifies the GET method of passing data to the CGI script.
  <form method="GET" ...>

 
This means the name parameters will be encoded and appended to the URL that invokes the CGI script.
 
Two named input fields are specified in the form: firstname and lastname.
  First Name: <input type="text" name="firstname">
  Last Name:  <input type="text" name="lastname">

 
For the purposes of this article the JavaServer has been installed in the directory /opt/JavaServer. Throughout JavaServer documentation you will see reference to the server root directory, often indicated as server_root when specified as code. For the remainder of this article consider server_root to and /opt/JavaServer to be equivalent. If you have installed the JavaServer in a different directory, be sure to make the appropriate adjustments when instructed to copy HTML, CGI, and servlet example programs to the appropriate directories.
 
Two input buttons are specified. Note that these inputs do not have names associated with them so their values will not be passed on as part of the forms data.
   <input type="submit"> <input type="reset">

 
These are standard HTML form inputs that have specific behaviors associated with them. An input of type submit causes the form to be submitted to the server when pressed. An input of type reset causes all fields to be reset to their default values without submitting the form.
 
If you get an error when you submit the form, be sure that you have set the file mode of the Perl CGI script file to executable. If you have not done this the JavaServer will indicate that the CGI program has thrown an exception.
 
Assuming that this listing has been placed in server_root/public_html, and the host name of the machine on which the server is running is cool1, the following URL will cause the above form to be displayed:
    http://cool1:8080/jdc-example01.html

 
Note: Similar in notion to server_root, you will see JavaServer documentation refer to a Server_Host_Name. Assuming you have accepted the default port address when you installed the server, the generic address of the default server home page is specified as:
    http://<EM><STRONG>Server_Host_Name
       </STRONG></EM>:8080

 
By default, the standard location of html files specified relative to the server_root
    <EM>server_root</EM>/public_html

 
For this article, the standard html directory is:
    /opt/JavaServer/public_html

 
and the JavaServer URL referring to the file, jdc-example01.html, in this directory would be
    http://cool1:8080/jdc-example01.html

 
Filling out the form with the First Name field set to "Greg" and the Last Name field set to "Voss" will cause the following URL to be invoked when the submit button is pressed:
    http://cool1:8080/cgi-bin/jdc-example01.pl?
             firstname=Greg&lastname=Voss

 
Note the key-value pairs of form data appended to the end of the URL following the question mark. An ampersand (&) is used to separate individual key-value parameters.
 
The Perl CGI script to be invoked was specified in the form tag of the HTML file:
      <form method="GET" action="cgi-bin/jdc-example01.pl">

 
Unless a fully qualified URL is given, the location of the script is relative to server_root, in this case:
 
    /opt/JavaServerBeta/cgi-bin/jdc-example01.pl
As a URL, this maps to:
    http://cool1:8080/cgi-bin/jdc-example01.pl

 
This is the actual URL invoked by the server when the form is submitted, minus the parameter data. The parameter data follows the question mark and can be specially encoded so that it contains only characters that are legally allowed in URLs.
    ?firstname=Greg&lastname=Voss
You see here the two key-value pairs or name-value pairs for the form just submitted.
 
Here's the code for the Perl CGI script, which will now process the client request:
#!/usr/local/bin/perl

##
## Print tags for beginng of HTML document to STDOUT
##


print <<EOM;
Content-type: text/html

<html>
<head><title>Welcome to the JDC</title></head>
<body>
<h1>Welcome to the JDC</h1>
<pre>
EOM

############################################################
##
##Read the parameters passed by the HTML form
##from the QUERY_STRING environment variable.
##
$query_string = $ENV{'QUERY_STRING'};

##
##Decode the form data encoded in the URL.
##
$query_string =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack (
                         "C", hex ($1))/eg;
$query_string =~ s/\+/ /g;

##
##Break up the parameters passed in the URL 
##into an array of key-value pairs.
##
@pairs = split (/&/, $query_string);

##
##Iterate over the array of key-value pairs,
##break up each pair into a key component and
##a value component. Build a hashtable, called
##form_data, allowing values to retrieved
##using a name key.
##
foreach $pair (@pairs) {
    ($key, $value) = split (/=/, $pair);
    $form_data{$key} = $value;
}

##
## Now parameter values can be retrieved from 
##the hashtable by supplying a name key.
##
$firstname = $form_data{"firstname"};
$lastname = $form_data{"lastname"};

##
## This is the dynamic content generated in
## response to the HTML form submission.
##
print "\n<h2>Greetings</h2>\n";
print "Hello $firstname $lastname. 
                    Welcome to the JDC.\n\n";
######################################################

##
##Print tags for end of HTML document 
##to STDOUT
print <<EOM;
</pre>
</body>
</html>
EOM

close OUT;

File: server_root/cgi-bin/ jdc-example01-simplified.pl
 
I'll do a simple walkthrough for those whose Perl skills are as rusty as mine.
 
The data that is printed to the standard output of the CGI script is the dynamically generated page. At the beginning and end of the file you'll see two short cuts, which are similar to 'here' files used in UNIX shell scripts. Anything appearing after a sharp sign (#) on a line is a comment. You should recognize the first example as a standard
 
HTML header. Everything between
    print <<EOM;
and
    EOM
is printed to the standard output.
##
##Print tags for beginng of HTML document 
##to STDOUT
print <<EOM;
Content-type: text/html

<html>
<head><title>Welcome to the JDC</title></head>
<body>
<h1>Welcome to the JDC</h1>
<PRE>
EOM


 
Similar code appears at the end of the CGI script to compose the end of the HTML page.
##
##Print tags for end of HTML document to 
##STDOUT
print <<EOM;
</PRE>
</body>
</html>
EOM


 
What you're really interested in, is the real dynamic content generation that depends upon the CGI input parameters appearing in between. The actual query string, the part of the URL following the question mark, can be retrieved from the QUERY_STRING environment variable:
$query_string = $ENV{'QUERY_STRING'};

 
However this string will be encoded to make it conform to the requirements of URL specification. To see how such encoding works, try submitting a name with spaces and other odd characters, for example, try submitting a First Name of "Dr. J. 6/9/97" and a last name of "Irving." You'll see an encoding that looks like this:
query_string: firstname=Dr.+J.+6%2F9%2F97&lastname=
                                             Irving

 
The spaces have become plus signs (+) and the forward slashes (/) have been hex encoded as %2F. The following Perl expression decodes any hex encodings in the query:
$query_string =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack (
                         "C", hex ($1))/eg;

 
The next expression turns the plus signs back into spaces.
$query_string =~ s/\+/ /g;

 
This is a standard decoding idiom used in many Perl CGI scripts.
 
Next, the query string is split into an array of pairs using the ampersand as a field separator.
@pairs = split (/&/, $query_string);
For the orginal submission, pairs would now be an array of two strings with a base index of 0:
   [0]"firstname=Greg"
   [1]"lastname=Voss"

 
The script now iterates over this array, and splits each element into key and value components using the equals sign in each string as a field delimiter:
    ($key, $value) = split (/=/, $pair);

 
Once a parameter is broken up into a name and a value, the parameter can be added to a hashtable called form_data:
    $form_data{$key} = $value;

 
The values can later be retrieved from this hashtable by using the name as a key:
$firstname = $form_data{"firstname"};
$lastname = $form_data{"lastname"};

 
At last you can print the dynamic content portion of the page being generated. Such pages are sometimes called virtual pages because they are created on the fly.
print"\n<h2>Greetings</h2>\n";
print "Hello $firstname $lastname.
         Welcome to the JDC.\n\n";

 
The first statement generates a standard HTML level 2 heading. The second statment issues a greeting substituting the firstname and lastname submitted in the form.
 
Here's a slightly more elaborate version of the first example CGI script. Some extra print stubs have been added for debugging and tracing purposes. When the form is submitted and this CGI script is invoked, you can follow the transformation of data from the hex decoding of the passed parameters all the way to the construction of the form_data hash table that allows the parameter values to be retrieved by a name key.
#!/usr/local/bin/perl

##
##Print tags for beginng of HTML document to 
##STDOUT
print <<EOM;
Content-type: text/html

<html>
<head><title>Welcome to the JDC</title></head>
<body>
<h1>Welcome to the JDC</h1>
<pre>
EOM

############################################################
print "\n<h2>Debug Info</h2>\n";

$content_length = $ENV{'CONTENT_LENGTH'};
print "content_length: " ,  $content_length, "\n";


##
##Read the parameters passed by the HTML form 
##from the QUERY_STRING environment variable.
##
$query_string = $ENV{'QUERY_STRING'};
print "query_string: ", $query_string, "\n";

##
## Decode the form data encoded in the URL.
##
$query_string =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack (
                        "C", hex ($1))/eg;
$query_string =~ s/\+/ /g;
print "query_string (decoded): ", $query_string, "\n";
print "\n";

##
##Break up the parameters passed in the URL 
##into an array of key-value pairs.
##
@pairs = split (/&/, $query_string);
print "pairs :", @pairs, "\n";
print "pairs[0] :", $pairs[0], "\n";
print "pairs[1] :", $pairs[1], "\n";

    
##
## Iterate over the array of key-value pairs,
## break up each pair into key component and
## value component. Build hashtable, called
## form_data, allowing values to retrived
## using name key.
##
foreach $pair (@pairs) {
  print "pair: ", $pair, "\n";
  ($key, $value) = split (/=/, $pair);
  print "key: ", $key, " value: ", $value, "\n";
  $form_data{$key} = $value;
}
print "\n%form_data: ", %form_data, "\n";
print "\nContents of %form_data hash table\n";
foreach $key (keys %form_data) {
    print "  $key: $form_data{$key}\n";
}

##
## Now parameter values can be retrieved from 
##the hashtable by supplying a name key.
##
$firstname = $form_data{"firstname"};
$lastname = $form_data{"lastname"};

##
## This is the dynamic content generated in
## response to the HTML form submission.
##
print "\n<h2>Greetings</h2>\n";
print "Hello $firstname $lastname. 
                      Welcome to the JDC.\n\n";
############################################################

##
##Print tags for end of HTML document to 
##STDOUT
print <<EOM;
</pre>
</body>
</html>
EOM

close OUT;

File: server_root/cgi-bin/ jdc-example01.pl




 
When this version of the CGI script is invoked, you'll see something like Figure 3.


Figure 3. Full Size



 
Because this is a GET form, the arguments appear appended to the URL in the browser's Location field:
  http://cool1:8080/cgi-bin/jdc-example01.pl?firstname=
                                   Greg&lastname=Voss

 
It may seem odd that two nearly identical HTML forms are supplied: jdc-example01.html and jdc-example01-simplified.html. Each of these HTML files has a corresponding Perl CGI script jdc-example01.pl and jdc-example01-simplified.pl.
 
The CGI script that prints more debug information does not have the text -simplified inserted in the name. The reference made to this CGI in the form tag must be changed as well. Only one line is different in the HTML files. You can use one file if you want to edit this line manually. The line
<form method="GET" 
action="cgi-bin/jdc-example01-simplified.pl">
has been changed to
<form method="GET" action="cgi-bin/jdc-example01.pl">
in the HTML form if you want debug information printed.
 
When the simplified form is submitted and processed by the CGI, a dynamically generated web page is returned by the browser by the server. The page should look like Figure 4.


Figure 4. Full Size



 
The name-value parameters also appear in this URL, but the window is too small to see them.
 
There are other CGI test scripts worth trying in the server_root/cgi-bin directory. Standard CGI tests provided with Appache and and Netscape servers include apache-test-cgi and test-cgi.pl. These print arguments (not form parameters) and environment variables so that you can check that the server is working as expected.
-----------------------------------------------------
/opt/JavaServerBeta/cgi-bin:
total 32
-rwxr-xr-x 1 gvoss  721 Mar 20 16:19 apache-test-cgi
-r-xr-xr-x 1 gvoss 1665 Mar  4 12:46 nph-test-cgi.pl
-r-xr-xr-x 1 gvoss  899 Mar  4 12:46 redirect.pl
-r-xr-xr-x 1 gvoss 1221 Mar  4 12:46 test-cgi.pl

-r--r--r-- 1 gvoss 1527 May 15 23:04 
                          jdc-example01-simplified.pl
-r--r--r-- 1 gvoss 2118 May 15 23:05 jdc-example01.pl
----------------------------------------------------

The HTML files that you need to copy to server_root/public_html are listed below for your convenience:
-----------------------------------------------------
/opt/JavaServerBeta/public_html:
-rw-rw-r-- 1 gvoss  683 May 15 23:20 
                        jdc-example01-simplified.html
-rw-rw-r-- 1 gvoss  683 May 14 03:05 
                                   jdc-example01.html
-rw-rw-r-- 1 gvoss  739 May 15 16:59 
                               jdc-example02-get.html
-rw-rw-r-- 1 gvoss  741 May 15 17:09 
                              jdc-example02-post.html
-rw-rw-r-- 1 gvoss  801 May 14 06:06 
                                   jdc-example02.html
-----------------------------------------------------


 
Many other HMTL files designed to test the example servlets supplied with JavaServer can be found in this directory as well.
 

Extending a JavaServer with Servlets

The usual way to extend web server functionality is to write CGI scripts. Servlets eliminate the need to resort to CGI solutions. However, CGI can still be used. If you have many existing CGI programs for serving up dynamic content, you can still use them. You'll probably want to convert at least those that are called frequently, because the memory overhead of invoking a CGI program is much greater than invoking a servlet service routine. Each time a CGI script is called, an entire operating system process is created. In contrast, servlet service routines are only light-weight threads. The executable code for the servlet only needs to be loaded once--the first time the service request associated with the service is invoked. After the first invocation, the code is called directly by the server with each request. In contrast, a CGI Perl script must be loaded into memory each time a service request is made. This is expensive for both processor and memory resources.
 
Step 1. Write the Servlet Below, you'll see Java code for the servlet equivalent of the CGI programs presented in the previous section. This source should be compiled with JDK 1.1 or later, and the resulting class file should be put in
    <EM>server_root</EM>/sevlets

 
In my case, I put the Java source file in that directory and compile there to create the class file:
    /opt/JavaServerBeta/servlets/JdcExample02.java
    /opt/JavaServerBeta/servlets/JdcExample02.class

 
Here's the servlet:
import java.io.*;
import java.servlet.*;
import java.servlet.http.*;
import sun.server.http.*;
import sun.misc.*;
import java.util.*;

public class JdcExample02 extends HttpServlet
{

//
//Initialize the servlet and set the html pages. Also
//@param stub Arguments passed by the servlet loader
//@return void
//
  public void init (
       ServletConfig config) throws ServletException
  {
    super.init(config);
  }

//
// Write to servlet response file.
// @param request The servlet request.
// @param response The servlet response.
// @return void.
//
  public void service (HttpServletRequest request, 
                        HttpServletResponse response)
    throws ServletException, IOException
  {
    Enumeration names = request.getParameterNames();
    PrintStream out = new PrintStream (
                        response.getOutputStream());

    response.setContentType ("text/html");
    out.println("<title>Welcome to the JDC (
                                     Servlet Version)
                 </title>");
    out.println("<h1>Welcome to the JDC (
                  Servlet Version)</h1>");
    out.println("<h2>Debug Info</h2>");

 //
 // Iterate over all key-value pairs from form and print
 //
  while ( names.hasMoreElements() )
    {
      String key, value;
      key = (String)names.nextElement();
      value = request.getParameter (key);
      out.println("key: " + key + " value: " + value);
      out.println("<br>");
    } 

 //
 // Retrieve key-value pairs by key lookup
 //
 String firstname = request.getParameter (
                              "firstname");
 String lastname = request.getParameter ("lastname");

  out.println("<h2>Greetings</h2>");
  out.println("<br>");
  out.println("Hello " + firstname + " " + lastname + ".");
  out.println("Welcome to the JDC.");

    out.close();
  }

}

File: server_root/servlets/ JdcExample02.java




 
Walking through this code, you'll notice it's quite a bit cleaner than the CGI scripts. For a minimal servlet, recall that two methods must be implemented to set up the basic service: init, and service.
 
The init method is invoked when the servlet is first loaded. This occurs on the first request for the service only; thereafter the servlet remains in memory. In this example, the init call is passed on to the superclass.
  public void init (
       ServletConfig config) throws ServletException
  {
    super.init(config);
  }


 
If you boil the service method down to its essence, it's really simple. If you know the names of the form parameters you want to print, you simply retrieve them and print them.
    String firstname =
       request.getParameter ("firstname");
    String lastname =
       request.getParameter ("lastname");
    ...
    out.println("Hello " + firstname +
                   " " + lastname + ".");

This is the essence of the dynamic content generation. All the data you need is contained in the request argument to service, which is an instance of HttpServletRequest. Instead of writing output to standard output, as in a CGI script, output is sent back to the server, and then to the client browser by writing to an output stream that can be retrieved from the second argument to service. This argument is an instance of HttpServletResponse and in this case is called response.
    PrintStream out = 
      new PrintStream (response.getOutputStream());
The first output you need to send to this stream is a header line indicating the content type of the response. This is done through the setContentType method of HttpServletResponse.
    response.setContentType ("text/html");
Note that this is not done through the output stream. That makes sense because this information is always required in the response header. Only the HTML codes and actual content are written directly to the output stream.
  out.println("<title>Welcome to the JDC (
  Servlet Version) </title>");
  out.println("<h1>Welcome to the JDC (
  Servlet Version)</h1>");
  ...
  out.println("<h2>Greetings</h2>");
  out.println("<br>");
  out.println("Hello " + firstname + " " + lastname + ".");
  out.println("Welcome to the JDC.");


 
Be sure to close the output stream before exiting to make sure the stream buffer is flushed:
    out.close();

 
There's one more piece of code not yet explained. Strictly speaking this code isn't necessary because you know all the names of the parameters you are expecting to send. But in case you did not know all the names in advance (or simply as a matter of convenience), you can iterate over all the parameters with an Enumeration:
    Enumeration names = request.getParameterNames();

 
You can now use the hasMoreElements method to test for the end of the parameter list:
    while ( names.hasMoreElements() )
      {
        ...
      }

 
You can retrieve the next parameter name or key from the nextElement method of Enumeration:
        String key, value;
        key = (String)names.nextElement();

 
Given the key string, you can lookup the parameter value from the response argument to the servlet with the getParameter method defined in HttpServletResponse
        value = request.getParameter (key);

 
Now you can do whatever processing or output you like with key and value:
        out.println("key: " + key + " value: " + value);
        out.println("<br>");

 
You'll frequently see loops of this structure in servlets:
 while ( names.hasMoreElements() )
  {
   String key, value;
   key = (String)names.nextElement();
   value = request.getParameter (key);
   out.println("key: " + key + " value: " + value);
   out.println("<br>");
  }


 
Figure 5 shows the virtual page generated by this servlet when it receives firstname=Greg and lastname=Voss as request parameters.



Figure 5.Full Size



 
Step 2. Install the Servlet Once you've compiled this servlet, you've covered Step 1, Writing the Servlet. In Step 2, you'll install it. Before you can get the servlet to work, you'll need to install it in the JavaServer with the JavaServer Administration Applet. This was covered in JavaServer Technologies, Part I . Recall, this is the second step of the three-step process for extending a JavaServer with a servlet:
  1. Write the servlet
  2. Install the servlet
  3. Run the servlet
Step 3. Run the Servlet As far as Step 3, you'll now need an HTML form to invoke the servlet. This HTML form code will be nearly identical to the code used in the CGI examples. The primary difference is in the action argument to the form tag.
 <form method="GET" action=/servlet/JdcExample02>

 
Here, the GET method of parameter passing is used, but the POST method could be used as well:
 <form method="POST" action=/servlet/JdcExample02>

 
No modification would be required to the servlet code to accommodate the POST method.
 
The action statement indicates the alias name of the servlet as specified when the servlet is installed with the JavaServer Administration Applet. In this case the servlet name and the class name are the same; they need not be. The first part of the pathname in the action attribute tells the server that a servlet is being invoked:
    action=/servlet/

 
The rest of the path names the actual servlet, in this case, JdcExample02. In most cases you'll want to put the servlet class in the default servlet directory:
  server_root/servlets/JdcExample02.class
For this article, this translates to:
  /opt/JavaServerBeta/servlets/JdcExample02.class

 
Here is the entire HTML form designed to invoke the above servlet:
-----------------------------------------------------
File: /opt/JavaServerBeta/public_html/
                               jdc-example02-get.html
-----------------------------------------------------

<html>
  <head>
   <title>JDC Registration Page (Servlet GET")</title>
  </head>

  <body>
   <h1>JDC Registration Page (Servlet Version)</h1>
    <h2>method="GET"</h2>

   <form method="GET" action=/servlet/JdcExample02"
        <PRE>
  First Name: <input type="text" name="firstname">
  Last Name:  <input type="text" name="lastname">

  <input type="submit">    <input type="reset">
        </PRE>
      </form>

  </body>
</html>


File: server_root/public_html/ jdc-example02-get.html



Encoding and Decoding Form Parameters
 
Decoding form parameter data passed to the servlet is not required with servlets as it is in CGI scripts. Basic functionality inherited from HttpServlet handles the decoding automatically. Instead you can directly access the key-value pairs created and encoded by the client browser directly inside the servlets service method. The decoded key-value pairs (sometimes called name parameters, derived from the name attribute associated with HTML input tags) can be retrieved directly from the first argument of the HttpServlet::service method. By convention this name is usually somthing like req or request to highlight the fact that it carries data associated with an HTTP request sent by the client browser.
 

Developing Servlets

As mentioned above, developing servlets is a three-step process, reviewed here, one last time, at the risk of driving you crazy:
  1. Write the servlet
  2. Install the servlet
  3. Run the servlet

 
Tricks for Testing Servlets If you don't want to write a full-blown web page to test your servlet, you can write a canned request by appending form parameters to the URL For example, to call the jdc-example01.pl Perl example script listed above, without writing and HTML form, you could simply type a URL that has the firstname and lastname parameters directly embedded:
    http://cool1:8080/cgi-bin/jdc-example01.pl?
    firstname=Greg&lastname=Voss

 
Programming challenge: To help you understand Java servlets, a good exercise would be to write a servlet called EchoFormParameters.java, that simply echos the form parameters that it receives. Such a program also provides a good test harness when you want to verify that your form is, in fact, passing the parameters you think it should.
 
Note, for a CGI script (Perl, shell-script, C, or other) the above type of canned query only works with a GET method of parameter passing. One of the subtle advantages of using servlets is that the servlet doesn't care whether the form has used the GET or POST method to pass arguments to the server.
 
This eliminates one of the primary disadvantages of using POST: you can't set up a bunch of canned queries to verify the parameters. Also, sometimes it makes sense to give the user a list of common queries encoded directly as links from a primary page. With servlets you can have the best of both GET and POST methods without maintaining two sets of server-side request-handler code.
 
To GET or to POST? That is the question CGI programmers face. There are advantages and disadvanges to either method of posting.
 
Note that the same servlet can handle both GET and POST methods when receiving form name parameters from a client browser request. The beauty of this duality is that you can embed canned queries in documents and pass them on to your server. Canned queries can be composed in a single line (either as the action argument of an HTML form statement, or by invoking the servlet directly from the browser with a special form of URL).
 
This is how a form encodes parameter data when the GET method of a document request is issued by the client browser. A question mark is appended to end of the actual URL followed by name parameter data pairs, with each pair being separated by an ampersand (&). Some encoding of data is also performed. Special characters, which cannot be part of a legal URL, are encoded as hexidecimal values preceded by a percent sign (%). Spaces are encoded as plus signs (+). Composing GET queries manually is handy for testing as you can compose dozens of different test service requests to excercise different code in your servlet's service routine without having to manually fill out a new form each time you want to invoke the request.
 
If you wanted to handle both GET and POST methods of form submission using normal CGI scripts, you would need two different scripts (or two different code branches controlled by a conditional). Because requests that pass a lot of data mostly use POST requests, it can be difficult to automate testing; you cannot simply specify all parameters in a single URL href tag as you could when using the GET request method. With servlets, canned queries are always an option because you can switch back and forth between GET and POST methods on request pages without altering any code in the servlet that handles and responds to the request.
 

Exploring JavaServer Directories

Here are some quick tips for familiarizing yourself with the most important files in the JavaServer distribution.
 
Start by studying the example servlets. You'll want to look at the form pages in the public_html directory as well as the corresponding servlets that handle form requests. The servlets are found in the servlets directory.
  /opt/JavaServerBeta/public_html
  /opt/JavaServerBeta/cgi-bin
  /opt/JavaServerBeta/servlets
Thus, the critical directories, relative to server_root are
    public_html
    cgi-bin
    servlets
In addition, you may want to explore the documentation directories:

  /opt/JavaServerBeta/system/doc:
  total 62
drwxrwxr-x 7 gvoss   512 Mar 4 15:56 .
drwxrwxr-x 6 gvoss   512 Mar 4 13:19 ..
drwxrwxr-x 2 gvoss   512 Mar 4 13:20 administration
drwxrwxr-x 3 gvoss  6144 Mar 4 13:20 apidoc
-rw-r--r-- 1 gvoss 17844 Mar 4 13:20 faq.html
drwxrwxr-x 2 gvoss   512 Mar 4 13:20 images
-rw-r--r-- 1 gvoss  3503 Mar 4 13:20 index.html
-rw-r--r-- 1 gvoss 12742 Mar 4 13:20 installation.html
-rw-r--r-- 1 gvoss  9744 Mar 4 13:20 knownbugs.html
-rw-r--r-- 1 gvoss  4736 Mar 4 13:20
                               release_notes.html
drwxrwxr-x 2 gvoss   512 Mar 4 13:20 security
drwxrwxr-x 2 gvoss   512 Mar 4 13:20 servlets



 

Example Servlets Distributed with JavaServer

JavaServer comes with a set of sample servlets that you can study and use as a starting point for writing your own custom servlets. Use the following URL to see a brief description of these servlets:
 http://<EM><STRONG>(your.server)</STRONG>
 </EM</system/doc/servlets/examples.html
For example, with a host name of cool1 and with JavaServer installed to use the default port, use:
 http://cool1:8080/system/doc/servlets/examples.html
This page contains links to run the example servlets, as well as links to the source code for the example servlets. Note, that when you view the examples.html file on the JavaServer site, rather than a downloaded version on your local machine, you will not be able to run the servlets directly. That's because the links assume that the JavaServer is up and running on your local machine. To see what these servlets do, download a copy of the Java server (with documentation), run it, and bring up
 http://<EM><STRONG>(your.server)</STRONG>
 </EM>/system/doc/servlets/examples.html

 
Here's a list of the example servlets provided with JavaServer:
         Simple
         Snoop
         Phone
         Counter
         Protected Servlet
         Date
         Hello World
         Finger
         Certificate Authority
         (requires Navigator client)


 
Remember that these servlet names won't map directly to Java class names. This is obvious from a quick look at the contents of the servlet directory:

/opt/JavaServerBeta/servlets:
total 24
drwxrwxr-x   4 gvoss   2048 May 14 07:00 .
drwxrwxr-x  13 gvoss    512 Mar  4 14:03 ..
-rw-r--r--   1 gvoss   2316 Mar  4 13:17
                        BBoardServlet.class
-rw-r--r--   1 gvoss   2794 Mar  4 13:17 
                        BBoardServlet.java
-rw-r--r--   1 gvoss   7268 Mar  4 13:17 CA.class
-rw-r--r--   1 gvoss  23720 Mar  4 13:17 CA.java
-rw-r--r--   1 gvoss    513 Mar  4 13:17
                        ChatServlet$ClientInfo.class
-rw-r--r--   1 gvoss   3619 Mar  4 13:17 
                        ChatServlet.class
-rw-r--r--   1 gvoss   4554 Mar  4 13:17
                        ChatServlet.java
-rw-r--r--   1 gvoss    322 Mar  4 13:17
                        ClientInfo.class
-rw-r--r--   1 gvoss    996 Mar  4 13:17 
                        ClientInfo.java
-rw-r--r--   1 gvoss   2545 Mar  4 13:16 Counter.class
-rw-r--r--   1 gvoss   2424 Mar  4 13:16 Counter.java
-rw-r--r--   1 gvoss    444 Mar  4 13:17
                        DBDataEncoder.class
-rw-r--r--   1 gvoss   1328 Mar  4 13:17
                        DBDataEncoder.java
-rw-r--r--   1 gvoss    760 Mar  4 13:17 
                        DBDataSimpleEncoder.class
-rw-r--r--   1 gvoss   1491 Mar  4 13:17 
                        DBDataSimpleEncoder.java
-rw-r--r--   1 gvoss    930 Mar  4 13:17 
                        DateServlet.class
-rw-r--r--   1 gvoss   1622 Mar  4 13:17
                        DateServlet.java
-rw-r--r--   1 gvoss   2542 Mar  4 13:17 
                        FingerServlet.class
-rw-r--r--   1 gvoss   3655 Mar  4 13:17
                        FingerServlet.java
-rw-rw-r--   1 gvoss    801 Mar 18 19:19
                        HelloServlet.class
-rw-r--r--   1 gvoss   1042 Mar  4 13:17 
                        HelloWorldServlet.class
-rw-r--r--   1 gvoss   1823 Mar  4 13:17
                        HelloWorldServlet.java
-rw-r--r--   1 gvoss   1664 Mar  4 13:17
                        InlineServlet.class
-rw-r--r--   1 gvoss   2075 Mar  4 13:17
                        InlineServlet.java
-rw-r--r--   1 gvoss   8858 Mar  4 13:17
                        LinkCheckerServlet.class
-rw-r--r--   1 gvoss  16872 Mar  4 13:17
                        LinkCheckerServlet.java
-rw-r--r--   1 gvoss   3012 Mar  4 13:16 
                        MailServlet.class
-rw-r--r--   1 gvoss   4676 Mar  4 13:16 
                        MailServlet.java
-rw-r--r--   1 gvoss    285 Mar  4 13:17 
                        MovieFinderException.class
-rw-r--r--   1 gvoss   7210 Mar  4 13:17 
                        MovieFinderServlet.class
-rw-r--r--   1 gvoss  11170 Mar  4 13:17
                        MovieFinderServlet.java
-rwxr-----   1 gvoss   2027 Apr 18 14:31
                        MovieFinderServlet.tag
-rw-r--r--   1 gvoss   2543 Mar  4 13:16 
                        PhoneServlet.class
-rw-r--r--   1 gvoss   3090 Mar  4 13:16
                        PhoneServlet.java
-rw-r--r--   1 gvoss   1062 Mar  4 13:16
                        ProtectedServlet.class
-rw-r--r--   1 gvoss   1538 Mar  4 13:16
                        ProtectedServlet.java
-rw-r--r--   1 gvoss   1772 Mar  4 13:17 
                        RedirectServlet.class
-rw-r--r--   1 gvoss   3433 Mar  4 13:17
                        RedirectServlet.java
-rw-r--r--   1 gvoss   3200 Mar  4 13:17 
                        ReleaseFormServlet.class
-rw-r--r--   1 gvoss   3830 Mar  4 13:17
                        ReleaseFormServlet.java
-rw-r--r--   1 gvoss   6183 Mar  4 13:17
                        RoomSchedServlet.class
-rw-r--r--   1 gvoss   7037 Mar  4 13:17
                        RoomSchedServlet.java
-rw-r--r--   1 gvoss   1605 Mar  4 13:17
                        SimpleFormServlet.class
-rw-r--r--   1 gvoss   1913 Mar  4 13:16
                        SimpleFormServlet.java
-rw-r--r--   1 gvoss   1047 Mar  4 13:16
                        SimpleServlet.class
-rw-r--r--   1 gvoss   1523 Mar  4 13:16 
                        SimpleServlet.java
-rw-r--r--   1 gvoss   3337 Mar  4 13:16
                        SnoopServlet.class
-rw-r--r--   1 gvoss   3533 Mar  4 13:16 
                        SnoopServlet.java
-rw-r--r--   1 gvoss    447 Mar  4 13:17 URLInfo.class
-rw-r--r--   1 gvoss    123 Mar  4 12:46 phonelist



 
To see the actual Java source file name, you can either use the status line of your web browser while reading the examples documentation page, or you can run the JavaServer Administration Applet and press the Servlets button to get a list of servlets with their corresponding class names, default arguments, and load specifications.

Security and Access Control

This article deals with extending the server rather than administering it. While you probably will want to become familiar with the server administration applet and various ways of setting up log files and security controls, initially you'll need to focus on ways to provide dynamic content for users of your service. Eventually, however, you'll want to use the JavaServer Administration Applet for managing user access to HTML pages, as well as to files and directories on your server.
 
Setting up password-controlled access to a given web page (or to a domain) is easy. Use the JavaServer Administration Applet. When you first invoke the applet, use admin for both login id and password.
 
Use port 9090 to get to the main JavaServer Administration page.
    http://cool1:9090

 
From here you can launch the administation applet. Or you can specify the applet directly.
    http://cool1:9090/applet.html

 
Again, substitute your host name in the above URLs.
 
Once the administration applet is running, you'll see a list of subcategories under the main entry titled "Java Webserver." With the "Web Page Service" category selected, press the "Manage" button near the bottom of the window.
 
A new applet page appears with buttons across the top. Press the "Security" button. Select the "Resources" category appearing in the tree at the left side of the new panel. A list of protected resources, in this case HTML files, appears in the main applet window. To added a new HTML file that requires password access, press the "Add" button below panel listing the resources.
 
A dialog appears like that in Figure 6.



Figure 6. Full Size



 
Add the relative pathname for the file. For this exercise I made a copy of the file protected.html in server_root/public_html and called it protected-gmv.html. Select the "Basic" scheme to get simple password protection for the file. The Administration servlet documentation covers the details of the "Basic" and "Digest" schemes. These are common protection mechanisms supported by other servers as well. Once you have added the file, it will appear in the list of protected resources as shown in Figure 7.



 
Figure 7.Full Size
 
Now when you try to access the new file, you'll be asked to enter the appropriate users id and password. Until you have set up your own specific user account you can use "admin" for both as when you login to the administration tool. Note that you only have to enter the password once. Thereafter the password data is maintained so you can travel about various protected pages and domains without having to constantly reenter your password.

JavaServer Documentation

A good place to start is with the servlet tutorial. The URL for this is
    http://cool1:8080/system/doc/
                      servlets/servlet_tutorial.html

 
Or you can look directly at the file in
 <EM>server_root</EM>/system/
                   doc/servlets/servlet_tutorial.html

 
For example:
 /opt/JavaServerBeta/system/doc/
                       servlets/servlet_tutorial.html

 
The example servlets provided with JavaServer also come with documentation. You can invoke the servlets from this documentation page or look at the source code for the servlets.
 http://cool1:8080/system/doc/servlets/examples.html

 
or, if you have access the server's file system, you can edit or view the examples.html file directly:
 <EM>server_root</EM>/system/
                          doc/servlets/examples.html
        

 
which for this article would appear as:
/opt/JavaServerBeta/system/doc/servlets/examples.html
                           

 
For basic JavaServer information, you'll want to look at the HTML files in
    <EM>server_root</EM>/system/doc



/opt/JavaServerBeta/system/doc:
total 62
drwxrwxr-x 7 gvoss   512 Mar 4 15:56 .
drwxrwxr-x 6 gvoss   512 Mar 4 13:19 ..
drwxrwxr-x 2 gvoss   512 Mar 4 13:20 administration
drwxrwxr-x 3 gvoss  6144 Mar 4 13:20 apidoc
-rw-r--r-- 1 gvoss 17844 Mar 4 13:20 faq.html
drwxrwxr-x 2 gvoss   512 Mar 4 13:20 images
-rw-r--r-- 1 gvoss  3503 Mar 4 13:20 index.html
-rw-r--r-- 1 gvoss 12742 Mar 4 13:20 installation.html
-rw-r--r-- 1 gvoss  9744 Mar 4 13:20 knownbugs.html
-rw-r--r-- 1 gvoss  4736 Mar 4 13:20 release_notes.html
drwxrwxr-x 2 gvoss   512 Mar 4 13:20 security
drwxrwxr-x 2 gvoss   512 Mar 4 13:20 servlets



 
The index.html file is the main entry to server documentation and installation.html should guide you through basic installation and configuration of your server. Assuming a host hame of cool1. These files will have the following URLs:
    http://cool1:8080/system/doc/index.html
    http://cool1:8080/system/doc/installation.html
You can either substitute your hostname in these URLs, or use and absolute file name to read the documents.

Server Paradise

This article has touched only the most basic aspects of developing servlets. There is an entire server and servlet programming API that makes it convenient to write complex services for your clients without having to focus on low-level details of HTTP protocols, request formats, and headers.
 
In addition, you'll want to learn more about server administration, including security and password management. You'll find you have full control of various access and event logs to monitor users and performance. You can mark specific servlets, files, and pages as inaccessible, or as requiring various levels of password protection using the JavaServer Administration Applet. Full documentation for the applet, as well as tutorials for writing servlets and installing the server and servlets, is distributed with JavaServer. You'll also find extensive API documentation and example programs to study.
 
To give you a sense of how much we like and trust JavaServers, a JavaServer is now hosting more than 10,000 members of the Java Developer Connection Web Site. We're thrilled with the performance. And now that we can write and maintain server extensions entirely in Java, our site development team seems to think it's died and gone to heaven. I hope you get as much out of JavaServers as we have.

Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.