Servlets, JDBC and PostgreSQL
Copyright © 2005
Yaodong Bi 


Introduction

Java Servlets, or simply servlets are a set of Java classes that can be used and extended for Web server-side programming provided the Web server supports Java servlets. Basically, the programmer specifies which servlet is to be used to process which request or which type of requests from client. Thus, when a request is received by the Web server, the Web server finds the proper servlet for the request. For example, in an HTML form,  its action clause can explicity specify which servlet be invoked to process the data submitted through the form. 

JDBC is an application programming interface (JDBC API) that defines a set of standard operations for interacting with relational database management systems (DBMSs). The DBMSs may be located on a remote machine connected to the Internet. In order to access a database under a specific DBMS, for example, PostgreSQL, one must have a driver for that DBMS and the driver must implement JDBC API. JDBC is a trademark name and not an acronym.

With HTML, Servlets, JDBC, and DBMS, we can easily build Web-based three-tier systems -- client, Web server, and database server. HTML is used to design the client-side interface that is to be executed on a Web browser such as Netscape and Internet Explore. Servlets can be employed to do server-side programming and JDBC can be used to interact with a database(s) for the requests from clients. The database(s) may be located on a remote database server.
This section describe how to use Servlets and JDBC and PostgreSQL to implement three-tier Web-based applications.

Using JDBC to Access PostgreSQL Databases

Basic Steps: 

Using JDBC to access databases can be described in six steps. The first step is to load the JDBC driver for the DBMS you need to interact with; the second step is to connect to the database; the third step is to create a statement, the fourth step is to query the database using SQL Select statements; the fifth step is to insert/delete/update data in the database. The fourth and fifth steps can be repeated as many times as needed by the application. When the application does not need to interact with the database, it should close all the resources, including ResultSet, Statement, and Connection, which should be the last step of using JDBC.

Step 1: Load the JDBC drivers

A JDBC driver is an implementation of JDBC API for a specific DBMS. A Java program can load several JDBC drivers at time. This allows the program to interact with more one database running under different DBMSs. The following line of code loads the JDBC driver for PostgreSQL,     

    Class.forName("org.postgresql.Driver"); 

Normally a JDBC driver is achived in a Java jar file and this jar file must be included in the CLASSPATH environment variable. You can download a copy of PostgreSQL JDBC driver by click here . However, you may want to search online to find the version of JDBC driver that matches the version of PostgreSQL.

  
Step 2: Connect to the database

A connection to a database can be established via the getConnection method of the DriverManager class. The getConnection method accepts three parameters -- the database, user name, and password. The following example connects to a database named "dbname" which is under PostgreSQL DBMS on mach.domain.edu, the user is "unu", and password is null.       

    String url = "jdbc:postgresql://server8.cs.uofs.edu/";
    String dbname = "dbname";
    String usernm = "unu";
    String passwd = "";
    Connection db = DriverManager.getConnection(
                    url+dbname, usernm, passwd);

Here, the url variable contains which JDBC driver is to used for this connection and also which machine, by IP address, hosts the DBMS and the database. 

Step 3: Create a statement

A Statement object has the ability to parse SQL statements, send the SQL statements to the DBMS, and accept the results returned from the DBMS.

    Statement st = db.createStatement();

Step 4 and 5: Interact with the database         

Normally, two opertions of Statement are needed to interact with a database. One is executeQuery(sql_select), which takes a SQL Select statement as its argument, sends the Select to the DBMS, and returns the results as an object of ResultSet. The other operation is executeUpdate(sql_insert_delete_update), which takes a SQL statement (Insert, Delete, or Update), sends it to the DBMS. Both operations throw a SQLException if the statement cannot be executed by the DBMS successfully.

The two operations normally may be used as often as the applicaton requires.

  
   String sql = "SELECT name, title " +
                 "FROM faculty f, course c " +
                 "WHERE f.id = c.instructor";
    ResultSet rs = st.executeQuery(sql);

    String faculty = '123456';
    String sql = "INSERT INTO faculty VALUES (" + 
                 "'" + faculty + 
                 "', 'Dave Letterman', 'Estate 1942', '941-6108')";
    st.executeUpdate(sql);    

Step 6: Disconnect from the database

When the application completes or no further database interaction is needed, you should return JDBC resources back to the system, which include, objects of Statement, ResultSet, and Connection.

    rs.close();
    st.close();

An Example

The following is a link to a real Java program with JDBC. It basically puts all the steps mentioned above together.     
 
Your First JDBC Program: SimpleJDBC.java


Using Servlets for Web-Server-Side Programming

Introduction

Sevlets are Java classes that can be used to enhance the functionality of WWW servers. Web-based servlets typically extend the HttpServlet class from the Java API that defines two methods to handle the two common types of requests. Method doGet() is designed to respond GET requests and method doPost() to respond POST requests. Both methods receive as arguments an HttpServletRequest object and an HttpServletResponset object that enable interactions between the client and the server. 

A Web application using servlets normally consists of two parts. One is an HTML file which runs on the client side. It contains an HTML form for the user to enter any data that is to be passed to the server as part of the request. The action clause of the form specifies which servlet be used to process the data. The specified servlet is invoked by the Web server to process the request along with passed data and it then it responds by sending information, which is normally a wegpage, back to the client. In the following an HTML file is shown and then the basic steps for designing servlets are described. 

Basic Steps for HTML

This HTML file invokes the SimpleServlet servlet designed above. It basically contains two parts. The second part includes a form which can accept input data from the user - user frist name and last name. The aciton for the form is to invoke the SimpleServlet servlet. Whent the user click the submit button, the servlet will be invoked by the web server. 
The relevant lines are highlighted in blue.  The first part uses JavaScript to do primitive data checking. for example, if you expect the user to enter the first name and last name, then JavaScript functions can be designed to check the two field before the request is sent to the Web server. Thus it can reduce unnecessary traffic on the Internet.

<html>
<head>
 <title>UOFSIS 0.6: Registrar www Interface</title>
<SCRIPT LANGUAGE="JavaScript">
<!--HIDE
 function check()
 {
  if (document.forms[0].firstname.value == "") {
   alert("Please Enter Your First Name!")
   return false
  }
  if (document.forms[0].lastname.value == "") {
   alert("Please Enter your Last Name!")
   return false
  } else {
   return true
  }
 }
//STOP HIDING-->
</SCRIPT>
</head> <body>
 <h1><center>Simple Servlet at UOFS</h1>
 <form action=http://localhost:8081/servlet/SimpleServlet" method= "POST"> 
  <pre> 
    First Name*: <input type="text" name="firstname" value=""> 
    Last Name*: <input type="text" name="lastname"value="">
  </pre>
  <center> 
  <input type="submit" name="request" value="submit your name"
                               onClick="return check()">
  <br><br>
  <input type="reset" value="Clear the Form">
 </form>
</body>
</html>

Basic Steps for Using Servlets

Step 1: Import Servlet Classes

Import the following classes:   

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

Step 2: Import Servlet Classes

Derive your servlet from HttpServlet:  
     
    public class SimpleServlet extends HttpServlet

Step 3: Put servlet initialization in the init() function

The init() function is executed only once when the servlet is first time executed. You may put JDBC connection or other initialization functions here. If you don't have any thing special, the following suffices.   

  public void init(ServletConfig config) throws ServletException
  {
    super.init(config);
  }

Step 4: In doPost(), process request and print in HTML the response

When a POST request is made by the client, doPost() will be invoked by the Web server. You can process the request and produce a response.
     

   public void doPost (HttpServletRequest req, HttpServletResponse resp) 
             throws ServletException, IOException
     { 
      String fname = req.getParameter("firstname"); 
      String lname = req.getParameter("lastname");         
      displayHTML(resp, fname, lname);

     }

The doPost() has two parameters - one for request and the other for response. The above segment of code shows how to get the value of a parameter passed from the HTML form. String literals "firstname" and "lastname" are the names for two text input boxes on the HTML form. Next will show how to print HTML text back the client.     

  private void displayHTML(HttpServletResponse resp, String fn, String ln)
             throws ServletException, IOException
     {
       PrintWriter out = resp.getWriter();
       resp.setContentType("text/html");
       out.println("<HTML><HEAD><TITLE>");
       out.println("Registrar Office");
       out.println("</TITLE></HEAD><BODY>");
       out.println("<H1><CENTER>Hello, "+fn+" "+ln+"</CENTER></H1>");
       out.println("<H1><CENTER>Your first servlet works!</CENTER></H1>");
       out.println("</BODY></HTML>");
       out.close();
    }


The above function prints HTML text back to the client. The body of this function could be included in the doPost() rather than in a separate function. Its first parameter is passed in by the doPost function. First, we get a PrintWriter which can be used to output HTML statements. Second, we set up the ContentType, then use the PrintWriter (out) to print HTML statements.

Step 5: Compile the Servlet and put the class in the servlet directory


Compile the servlet program.

         javac SimpleServlet.java

Source Code:
  1. SimpleServlet.htm:  
  2. SimpleServlet.java
Web Application Deployment with Tomcat

Standard directory structures with Tomcat

A Web application is defined as a set of directories and files in a standard layout. The top-level directory of your Web application hierarchy is also the document root of your application. When the Tomcat manager deploys your application into the Tomcat web server, he or she assigns a context path, which is normally the name of your application, to your application. Thus, if your application is, for example, E-Movie, and it is assigned as the context path, then users of the application would enter http://web-server-host/E-Movie/index.html tto access the index.html of your application saved in the root directory. The context path appears as a directory in the directory of $TOMCAT_HOME/webapps/ and it normally contains following directories and files:

HTML files
The HTML files along with other files (such as JavaScript, stylesheet files, and images) that constitute the user interface are stored in the root directory (context path) of your application.  .

/WEB-INF/web.xml 
The web.xml is called the Web Application Deployment Descriptor for your application. This XML file normally consists of three segments: the first segment defines the servlets of the application, the second defines what Web link(s) would invoke the execution of the doPost() or doGet() operation of which servlet, the third normally defines initialization parameters. The following shows the web.xml for the SimpleServlet example. You may want to look back at the form action clause in the SimpleServlet.html file to see how that web page specifies the SimpleServlet servlet as the server-side program that is to invoked to process the form data when the form is submitted

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    " http://java.sun.com/dtd/web-app_2_3.dtd">
   
<web-app>
    <display-name>Web Application Example</display-name>
    <description>
      Simple Servlet Example
    </description>

    <!-- Define servlets that are included in the example application -->
    <!-- First line defines a name for the servlet -->
    <!-- second line specifies where the .class file is for that servlet -->
    <servlet>
        <servlet-name>SimpleServlet</servlet-name>
        <servlet-class>edu.scranton.cs.bi.web.SimpleServlet</servlet-class>
    </servlet>

    <!-- the above definition may be repeated as needed 
    <servlet>
        <servlet-name>AnotherServlet</servlet-name>
        <servlet-class>edu.scranton.cs.bi.web.AnotherServlet</servlet-class>
    </servlet>
    -->

    <!-- Specifies what URI the above defined servlet is to be invoked -->
    <!-- First line must be a servlet name defined above -->
    <!-- second line specifies what URI the named servlet is invoked -->
    <!-- URI: http://host/context-path/servlet/SimpleServlet-->    
    <servlet-mapping>
        <servlet-name>SimpleServlet</servlet-name>
        <url-pattern>/servlet/SimpleServlet</url-pattern>
    </servlet-mapping>

    <!-- URI: http://host/context-path/SimpleServlet     
    <servlet-mapping>
        <servlet-name>AnotherServlet</servlet-name>
        <url-pattern>/AnotherServlet</url-pattern>
    </servlet-mapping> 
    -->   
</web-app>


/WEB-INF/classes/
This directory contains all your servlet class files and all the other java classes files that are used in your application. Don't put any JAR files in this subdirectory. If your classes are in Java packages, you will have to define the package directory structure under this /WEB-INF/classes/ directory. For example, a Java class named edu.scranton.cs.bi.web/SimpleServlet.class would be stored in a file named /WEB-INF/classes/edu.scranton.cs.bi.web/SimpleServlet.class.

/WEB-INF/lib/
This directory is where you store all java JAR files, such as JDBC drivers.  

Accessible classes/JARS in Tomcat
All classes in the WEB-INF/classes/ directory and classes in JAR files stored in the WEB-INF/lib/ directory, and classes stored in  $TOMCAT_HOME/common/ and $TOMCAT_HOME/shared/ are made, by the Tomcat, visible  and accessible to other classes within your web application. This works like as if Tomcat defined a CLASSPATH variable which include all those directories and all jar files when your application is executed under Tomcat. Thus, for example, if you want the PostgreSQL's JDBC driver, pg73jdbc3.jar, accessible in your application, simply copy it to your Context_Path/WEB-INF/lib/ directory.


Development and Deployment with Eclipse
When you create a Tomcat project using Eclipse, the directory structure described above is created automcatically by Eclipse. HTML files , e.g., SimpletServlet.htm , are stored in the root directory of the project, dot-java (.java) files, e.g., SimpleServlet.java, in the src directory, the JDBC drivers (JAR file), e.g., pg73jdbc3.jar, in WEB-INF/lib/. WEB-INF/classes/ is also created, but not displayed in Eclipse since the programmer does not need to access any files stored in this directory. WEB-INF/web.xml is created as a template, and you need to edit it to suit your application.

When the project is built and deployed (by selecting proper options in the Ant Build...), the dot-class (.class) files are generated and stored in WEB-INF/classes/, and then the directory structure is copied to $TOMCAT_HOME/webapps/. You may want to look into build.xml and build.properties two files to see how the configuration files for build and deployment.


Development and Deployment without any IDE
This part describes how to develop and deploy Web applications manually, i.e., with no help from any integrated development environment such as Eclipse. Hopefully, through this manual process, you have a better understanding of the directory structure of Tomcat and its relationship with the development environmnet.

Step 1:  Create an directory structure for development

Create a directory named WebHello in C:\, and then create WEB-INF in WebHello\, and then WEB-INF\classes\ and WEB-INF\lib\ in WEB-INF. So we have:
      C:\WebHello\
      C:\WebHello\WEB-INF\
      C:\WebHello\WEB-INF\classes\
      C:\WebHello\WEB-INF\lib\

Step 2: Put files in proper places

Create SimpletServlet.htm and save it in C:\WebHello\ directory, and create SimpletServlet.java and save it in C:\WebHello\ directory

Step 3: Compile java servlets

Change directory to C:\WebHello\; and then compile SimpletServlet.java:

      javac -d WEB-INF\classes -cp $TOMCAT_HOME\common\lib\servlet-api.jar SimpleServlet.java 

Here, $TOMCAT_HOME refers to the path where your Tomcat is installed. If you have followed this tutorial from the beginning, you can compile your program using the following command (as one line):

javac -d WEB-INF\classes -cp "c:\Program Files\Apache Software Foundation\Tomcat 5.5\common\lib\servlet-api.jar" SimpleServlet.java

Note that we are compiling the servlet program under Windows XP, and so we need to specify where the Java Servlet package is located in the command line using the -CLASSPATH (-cp) option. As mentioned in Accessible classes/JARS in Tomcat section, when this servlet is executed, the classes needed from servlet-api.jar would be found by Tomcat since it is stored in $TOMCAT_HOME/common/ directory.

Step 4: Copy the application to Tomcat for deployment

You may use the xcopy command to copy the WebHello directory and all files and subdirectories in it to $TOMCAT_HOME\webapps\ if you figure out the syntax of xcopy. However, the simplest way to do this step is, in Microsoft Windows XP's Explore, copy the WebHello directory and the paste it into $TOMCAT_HOME\webapps\. If you followed this tutorial, after copying you should see the following directory:

    c:\Program Files\Apache Software Foundation\Tomcat 5.5\webapps\WebHello\

Step 5: Deploy the application by a Tomcat manager

Start your tomcat server and use a browser to log into the server as a manager, and deploy WebHello. Enter the following in a web browser

          http://localhost:8081/WebHello/SimpleServlet.htm

Step 6: Test the application

In the displayed form, enter your first and last name as requested and then click submit. if everything goes well, it should display a message like "Hello, First Name Last Name, your first servlet works".


HttpServletRequest and HttpServletResponse API

HttpServletRequest API

The HttpServletRequest object passed by the WWW server to the doGet or doPost methods contains the request from the client. It provides a rich set of methods for accessing request parameters. A short list of those includes:
  • String getParameter(String name): return the value of a parameter indicated by the name parameter as part of the GET or POST requests
  • Enumeration getParameterNames(): return the names of all the parameters of a GET or POST request.
  • String[] getParameterValues(String name): return an array of strings containing the values for a specified servlet parameter.
  • Cookie[] getCookies(): return  an array of Cookie objects stored on the client by the server. Cookies can be used to uniquely identify clients to the server.
  • HttpSession getSession(boolean create): return an HttpSession object associated with the client's current browsing session. HttpSession severs a similar purpose as cookies.
HttpServletResponse API

The doGet and doPost methods receive an object that implements the HttpServletResponse interface. The interface provides a set of methods for sending information back to the client. A list of commonly used methods are listed below:
  • void setContentType(String type): Specifies the type of response back to the browser. For example, "text/html" speecifies the response is an HTML document.
  • PrintWriter getWriter(): returns a text-based output stream for text data to be sent back to the browser. For example, it can be used to print the HTML statements to the browser..
  • ServletOutputStream getOutputStream(): return a binary output stream for binary data to be sent back to the browser.
  • void addCookie(Cookie cookie): add cookies to the client's browser.