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

Servlets, Forms, and Databases

Java Programming, Lecture Notes # 682, Revised 2/3/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 January 4, 1999. The sample 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 running as localhost on the same machine. The servlet was also tested using the JavaSoft Java Web Server 1.1.1 program running on a different machine on the network.

All tests required the use of the Windows version of the mSQL 2.0 database program from http://blnet.com/msqlpc/downloads.htm#win and the JDBC interface classes for mSQL and JDK 1.2 from http://www.Imaginary.com/Java/.

Introduction

The primary purpose of this lesson is to introduce you to the following concepts:

The lesson also illustrates the use of a servlet to access a database to retrieve data and send it back to a client, but this was covered in an earlier lesson.

Sample Program

The name of the sample program is Servlet02. This servlet performs the following operations:

The client has the ability to either cause the existing table to be deleted and add data to a new table, or to simply add new data to an existing table. The data provided by the client consists of two strings, one representing a first name and the other representing a last name. Each time the client submits data, all of the data is retrieved from the table and sent back to be displayed on the client screen.

The program was tested using three different computers on a network, all running JDK 1.2 under Win95. The HTTP server program from JavaSoft named Java Web Server 1.1.1 was running on one machine. The database server program named mSQL was running on a second machine. A browser was running on the third machine

An HTML form file named Servlet02.htm containing three fields and one submit button was loaded into the browser. The three fields were:

The servlet was activated and data was sent to the server by the highlighted tags from the HTML file shown below. If you aren't familiar with the HTML syntax for creating and processing forms, you will need to look this up in an appropriate HTML book or tutorial. Many such documents are freely available on the web.

<FORM METHOD=GET 
ACTION="http://webserver:8080/servlet/Servlet02">
Enter your name and press the button<P>
Clear Database, y or n: <INPUT TYPE=TEXT NAME="clear"><P>
First Name: <INPUT TYPE=TEXT NAME="firstName"><P>
Last Name: <INPUT TYPE=TEXT NAME="lastName"><P>
<INPUT TYPE=SUBMIT>

These tags caused a GET method to be sent to the server and caused the server to call the servlet named Servlet02. The request from the client was handled by an overridden doGet() method in the servlet.

The servlet got a connection to a specified mSQL database server on the machine named node3 using the following URL:

jdbc:msql://node3:1114/JunkDB

Note that the // is part of the URL and is not a comment indicator in this case.

Then, the code in the servlet obtained the value of the parameter named clear from the client. If the value was either Y or y, and a table named servlet02Table already existed, it was deleted.

Next, the servlet created a new table named servlet02Table if a table of that name didn't already exist

The servlet then got the values for the parameters named firstName and lastName from the client and inserted them into the database table.

After this, the servlet

The program was also successfully tested using the JavaSoft servletrunner program running on localhost as a substitute for the HTTP server. In this case, only two different machines were involved: one for the browser and servletrunner and one for the database server.

Interesting Code Fragments

The first fragment is shown simply to remind you of the requirement to import special packages dealing with servlets and JDBC.

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

The next fragment shows the beginning of the overridden doGet() method, and should remind you that each of the service() methods receive two objects as parameters. One object passes data from the client to the servlet. The other object passes data from the servlet to the client.

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

The next fragment declares two local reference variables that you will need to know about when they are used later.

      Statement stmt;//used for database access
      ResultSet rs;//used for database access

As discussed in an earlier lesson, it is necessary to set the content type of the data to be returned to the client before accessing the writer or stream that will be used to return that data. This is illustrated in the following fragment that sets the content type to the standard for HTML text. At some point, you will probably want to find a good reference that discusses all of the possible content types.

      res.setContentType("text/html");

The next fragment gets an output writer object that will be used to send data back to the client. It also begins constructing the tags and other information that is required to construct an HTML page on the fly.

      PrintWriter out = res.getWriter();

      out.println("<HTML>");
      out.println("<HEAD><TITLE=Servlet02</TITLE></HEAD>");
      out.println("<BODY>");

The next fragment registers the JDBC driver for the mSQL database server, constructs a URL for accessing that database, and gets a connection to the database. It also causes the URL to be displayed on the client screen.

      Class.forName("com.imaginary.sql.msql.MsqlDriver");
      String url = "jdbc:msql://node3:1114/JunkDB";
      Connection con = DriverManager.getConnection(url,
                                            "baldwin", "");
      out.println("URL: " + url + "<br><br>");

The next fragment gets a Statement object linked to the database connection to be used later for manipulating the database.

       stmt = con.createStatement();

Up to this point, with the exception of the HTML material for an HTML form, everything that I have presented in this lesson was presented in an earlier lesson. The following fragment shows some new material.

This fragment gets the incoming parameter named clear from the client. If the value of the parameter is either Y or y, an attempt is made to delete the existing database table. Note that clear is the name of a local reference variable in the method, and "clear" as a parameter to the getParameter() method is a string that matches the name of the data-input field on the HTML form. There is no requirement for these two names to match. It just seemed like a good idea at the time.

      String clear = req.getParameter("clear");
      if(clear.toUpperCase().equals("Y")){//Delete table
        try{
          stmt.executeUpdate("DROP TABLE servlet02Table");
        }catch(Exception e){
          out.println(e + "<br>");
          out.println(
                    "No existing table to delete<br><br>");
        }//end catch
      }//end if(clear.toUpperCase().equals("Y")

The next statement shows that the servlet tries to create a new database table each time it is invoked. If a table with the same name already exists, the attempt to create a new table is aborted and an exception is thrown. The exception is essentially ignored.

      try{
        stmt.executeUpdate("CREATE TABLE servlet02Table ("
                + "lastName char(15),firstName char(15))");
      }catch(Exception e){
        out.println(e + "<br>");
        out.println(
                  "Table exists, can't create it<br><br>");
      }//end catch

The next fragment shows some more material that is new to this lesson. This fragment uses the getParameter() method of the incoming request object to obtain the values of the first and last name fields. Then this new data is inserted into (added to) the data already in the database table.

Pay particular attention to the requirement to surround the new data with single quotes to satisfy the SQL syntax requirement for string data.

      String firstName = req.getParameter("firstName");
      String lastName = req.getParameter("lastName");
 
      stmt.executeUpdate("INSERT INTO servlet02Table ("
                    + "lastName, firstName) VALUES('" 
                    + lastName + "','" + firstName + "')");

The next fragment creates a Statement object and uses that object to execute a query on the database. The result of the query is encapsulated in an object of type ResultSet that is referred to by the reference variable named rs.

      stmt = con.createStatement();

      rs = stmt.executeQuery(
         "SELECT * from servlet02Table ORDER BY lastName");

The objective here is to send all of the data in the database table back to the client for display on the client screen. The next fragment uses methods of the ResultSet class to extract the pertinent data from the ResultSet object. Then it is formatted as HTML and handed over to the output writer for transmission to the client.

      out.println("Contents of Database<BR>");
      while(rs.next()) {
        lastName = rs.getString("lastName");
        firstName = rs.getString("firstName");
        out.println(lastName + ", " + firstName);
        out.println("<BR>");
      }//end while loop

The next fragment constructs the remaining tags required by the HTML format and closes the connection to the database.

      out.println("</BODY></HTML>");
      con.close();

This is followed by some routine wrap-up code that is not shown here, but which you can view in the complete listing of the program in the next section.

Program Listing

A complete listing of the program follows.

/*File Servlet02.java, Copyright 1999, R.G.Baldwin
Rev 1/4/99

The purpose of this program is to illustrate:
1. The use of a servlet to get data from a client form.
2, The use of a servlet to access a database to store
   data obtained from the client form.
3. The use of a servlet to access a database to retrieve
   data and send it back to a client.


The program was tested using three computers on the 
network, all running JDK 1.2 under Win95.

For this test, the HTTP server program from JavaSoft 
named Java Web Server 1.1.1 was running on one machine.

The database server program named mSQL was running on the 
second machine.

A browser was running on the third machine

An HTML file containing three fields and one submit button
was loaded into the browser.  The three fields were:
  
clear (y or n)
firstName
lastName

The servlet was activated by the following tag in the
HTML file.

<FORM METHOD=GET 
ACTION="http://webserver:8080/servlet/Servlet02">

This tag caused a GET method to be sent to the server and
caused the server to call the servlet named Servlet02. The
request from the client was handled by an overridden
doGet() method in the servlet.

The servlet got a connection to a specified database
server on the machine named node3 using the following URL:
  
jdbc:msql://node3:1114/JunkDB

Then, the code in the servlet obtained the value of the
parameter named clear from the client.  If the value was
either Y or y, and a table named servlet02Table already
existed, it was deleted.

Next, the servlet created a new table named servlet02Table
if a table of that name didn't already exist

The servlet then got the values for the parameters named
firstName and lastName from the client and inserted them
into the database table.

After this, the servlet accessed the database server, got
all of the names in the table ordered by last name, 
formatted that data into an HTML page and returned the page
to the browser where the list of names appeared in the
browser window.

The program was also successfully tested using the JavaSoft 
servletrunner program running on localhost as a substitute
for the HTTP server.  In this case, only two different
machines were involved:  one for the browser and 
servletrunner and one for the database server.
**********************************************************/
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;

public class Servlet02 extends HttpServlet{
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res)
                      throws ServletException, IOException{
                        
    try {
      Statement stmt;//used for database access
      ResultSet rs;//used for database access

      //Set the content type of the data to be sent back
      // to the client.
      res.setContentType("text/html");
      
      //Get an output writer object to send data back to
      // the client.
      PrintWriter out = res.getWriter();
      
      //Begin constructing the HTML page to send back to
      // the client.
      out.println("<HTML>");
      out.println("<HEAD><TITLE=Servlet02</TITLE></HEAD>");
      out.println("<BODY>");
      
      //Register the JDBC driver
      Class.forName("com.imaginary.sql.msql.MsqlDriver");
      //Construct URL for database on node3
      String url = "jdbc:msql://node3:1114/JunkDB";
      //Get a connection to the database
      Connection con = DriverManager.getConnection(url,
                                            "baldwin", "");
      //Display the URL on the client screen
      out.println("URL: " + url + "<br><br>");
 
      //Get a Statement object
      stmt = con.createStatement();

      //Get the incoming parameter named clear from the 
      // client. If it is Y or y, delete the existing
      // table.
      String clear = req.getParameter("clear");
      if(clear.toUpperCase().equals("Y")){//Delete table
        try{
          stmt.executeUpdate("DROP TABLE servlet02Table");
        }catch(Exception e){
          out.println(e + "<br>");
          out.println(
                    "No existing table to delete<br><br>");
        }//end catch
      }//end if(clear.toUpperCase().equals("Y")
      
      //Create a new table named servlet02Table in the 
      // database if it doesn't already exist
      try{
        stmt.executeUpdate("CREATE TABLE servlet02Table ("
                + "lastName char(15),firstName char(15))");
      }catch(Exception e){
        out.println(e + "<br>");
        out.println(
                  "Table exists, can't create it<br><br>");
      }//end catch
      
      //Get the two incoming data parameters from the
      // client
      String firstName = req.getParameter("firstName");
      String lastName = req.getParameter("lastName");
        
      //Put the data into the database table. Don't forget
      // to enclose the string data in single quotes to 
      // satisfy the SQL syntax requirement.
      stmt.executeUpdate("INSERT INTO servlet02Table ("
                    + "lastName, firstName) VALUES('" 
                    + lastName + "','" + firstName + "')");
      
      //Create a statement object linked to the database
      // connection.
      stmt = con.createStatement();

      //Use the statement object to execute a query on the
      // database.
      rs = stmt.executeQuery(
         "SELECT * from servlet02Table ORDER BY lastName");

      //Extract data from the ResultSet object and display
      // in the HTML page sent back to the client.
      out.println("Contents of Database<BR>");
      while(rs.next()) {
        lastName = rs.getString("lastName");
        firstName = rs.getString("firstName");
        out.println(lastName + ", " + firstName);
        out.println("<BR>");
      }//end while loop

      //Finish the construction of the html page
      out.println("</BODY></HTML>");

      //Enable the following statement to delete the table
      // when the servlet terminates.
      //stmt.executeUpdate("DROP TABLE servlet02Table");
      
      //Close the connection to the database      
      con.close();
    }catch( Exception e ) {
      e.printStackTrace();
    }//end catch
  }//end doGet()
}//end class Servlet02

-end-