[View INPRISE Home Page][View Product List][Search This Web Site][View Available Downloads][Join Inprise Membership][Enter Discussion Area][Send Email To Webmaster]
JBuilder Home Page

Building Java Servlets with JBuilder
Written by Live Software, Inc.

NOTE: The views and information expressed in this document represent those of its author(s) who is solely responsible for its content. Borland does not make or give any representation or warranty with respect such content.

What are Java Servlets?

Java Client Technology
Many new client-side technologies have emerged that greatly enhance the abilities of client-side "applications". Technologies such as Dynamic HTML, VBScript, and JavaScript leave little room for arguing that the use of ActiveX objects or Java applets on the client is warranted. These new technologies, specifically Dynamic HTML (DHTML), allow for an entire new level of sophistication and capability on the client.

With DHTML, interactive, dynamic applications can be created simply through the use of HTML and a collection of new DHTML tags. Applications with tabbed interfaces, drag-and-drop, menus, forms, and a host of other features, are all possible with DHTML. Because traditional server-side processing like database connectivity and legacy system access, is, by definition, performed at the server, DHTML is an extremely viable solution for client-side applications. The server can still perform its required tasks, but the client application can be created more quickly, can be more compatible across platforms, and can be modified and deployed in shorter time.

Targeted Deployment
Getting rid of applets on the client is not the goal here. For wide-audience deployment, such as the Internet, JavaÆs competing technologies are a more compelling solution. Nevertheless, applets still have their place in a more targeted deployment, where client choice is under complete control. For example, an Intranet or Extranet deployment allows for greater control over the client application. Another example might be an administration applet for your application. As a developer, you can make demands from your users about how to administer or use your system, perhaps through an applet, but on the Internet, this level of control is not available.

Server-Side Java
The power of server-side Java is made evident when looking at the limitations of client-side Java. Table 1.1 gives a quick rundown of the features of server-side Java.

Capability

Client-Side Java

Server-Side Java

Consistent Java Features

 

X

Use latest Java Technologies

 

X

Use Java VM of Choice

 

X

No Browser Limitations

 

X

Client Irrelevant

 

X

Table 1.1

In most respects, server-side Java is the complete opposite of client-side Java. With server-side Java, many, if not all, of the limitations of applets are gone. As a developer, you now have complete control over your Java virtual machine, what features and capabilities you can use, and on what platforms you run your server-side application.

Server-side Java allows you to completely realize JavaÆs "write once, run anywhere" goal. The full capabilities of the language are available to you with no limitations or restrictions imposed. If you want to use MicrosoftÆs J/Direct technology or SunÆs RMI technology, you can do so without concern for your clientsÆ ability to run these applications. Since these applications run on the server, you are also in complete control over the platform, the operating system, and every aspect of the environment your application runs in.

Java on the server is a true unifying solution for your application development. Because you now have complete control over your environment, you can now develop on one platform and deploy on another, with great confidence that it will run properly on both platforms. Because the interface is now handled with DHTML or a similar technology, you now have a truly portable system.

With all of the power server-side Java affords you, including all of the inherent benefits of Java û object-oriented, strong type-checking, large set of built-in classes, etc. û there is still one shortcoming, a consistent server-side API. Why is this important? It is not enough to say that Java on the server will answer all of your problems. More importantly, we want to use Java as the development platform across all servers. Additionally, we want to be able to combine multiple applications together into a larger system. There is an answer to this problem, Java Servlets.

Java Servlets

Java Servlets are platform-independent, server-side programs written using the Java Servlet API, part of the Java Platform. Java Servlets bring the power of "write once, run anywhere," Safe Network Delivery, and Smart Card to Supercomputer scalibility to server-side applications. Traditional server-side applications and extensions written in Perl, C/C++, or other languages, can be replaced through the use of Servlets. By using Servlets as an extensible, well-defined cross-platform environment, sophisticated applications for the server become easier to develop, faster to deploy, and more cost effective to maintain.

By using existing mature server technology, such as Web servers, in combination with Servlets, sophisticated applications can be written that hide the complexities and platform-specific behaviors of the particular server implementation. Using Servlets, the developer doesn't have to worry about the inner workings of the server. Form data, server headers, cookies, etc. are all handled for you by the Servlet API's underlying classes. One of the biggest differences between todayÆs server-side applications and Servlets is performance. There's a single Java virtual machine running on the server and the servlet is loaded once when it is called. It's not loaded again until the servlet changes, and a modified servlet can be re-loaded without restarting the server or application.

The servlet stays resident in memory and it's very fast. Static or persistent information can be shared across multiple invocations of the servlet, allowing you to share information between multiple users. Servlets are also modular; each servlet can perform a specific task and then you can tie them together. In short, Servlets can talk to each other.

What does a servlet look like? Figure 1 shows the complete source code to a functioning servlet.


import java.io.*;
import javax.servlet.*;
                             
public class SimpleServlet extends GenericServlet
{
public void service(ServletRequest req, ServletResponse res)
      throws ServletException, IOException
{
ServletOutputStream out = res.getOutputStream();
                                             
out.println("<HEAD><TITLE> SimpleServlet Output ");
out.println("</TITLE></HEAD><BODY>");
out.println("<h1> SimpleServlet Output </h1>");
out.println("</BODY>");
	}
}

Figure 1

A Server Component Model
Servlets are more than just a replacement for todayÆs server-side programs, but with the features inherently available in Servlets, they become a true component model for building server-side applications. Servlets have many unique features, but two in particular extend the ability of this server-side system into a component model for server-side applications. These two features are Servlet chaining and inter-servlet communications.

Servlet chaining is the ability for one ServletÆs output to be æpipedÆ in to the input of another Servlet. This can continue for multiple servlets. This simple yet powerful notion means that different servlets, perhaps from different vendors, can work together seemlessly. For example, let say you had a spelling checker servlet. This servlet could be chained after any other servlet to spell check any of the ouput being sent to the client. This model for server-side application invocation means that a greater capability can be harnessed from the combination of lesser-capability servlets.

Another example might be a language translation servlet. A servlet that perhaps converts English to German could be used to dynamically convert all of our servletsÆ output into a different language. For example, you could chain your servlet to the spell checker servlet then to the German translator servlet. Each servlet need not know about the capabilities of the other, yet they can all work seemlessly together. This is possible because of the use of a consistant server-side API, the Servlet API.

The other powerful capability of Servlets is their ability to "communicate" with each other. That is, one servlet can request the services of another servlet. For example, let say you created a servlet that handled database connectivity. You could have that servlet loaded on Web server startup, then any subsequent servlet could use the facilities of the database servlet without implementing database code directly. Figure 2 shows a portion of code that exemplifies such a behavior.


DatabaseServlet dbServlet =
(DatabaseServlet) context.getServlet ("DatabaseServlet");
ResultSet rs = dbServlet.executeQuery("SELECT * From Table");
Figure 2

Figure 2 shows how a servlet could request another servlet by name then execute a method, in this case, an SQL query that returns a ResultSet object. Any servlet could make use of that method.

Servlets as a CGI Replacement

One of the main problems with traditional CGI applications is performance. A new process is created each time a CGI application is requested by the client. This can lead to performance problems at popular web sites that handle requests from multiple users. Servlets, on the other hand, handle this process more efficiently. The first time a servlet is requested, it is loaded into the web serverÆs memory space. Subsequent client requests for the servlet result in calls to the servlet instance in memory. Also, servlets can use threading to process multiple requests efficiently if the JVM embedded in the web server offers thread support, whereas CGI programs are not threaded.

Another benefit of servlets over CGI is that servlets are platform-independent, whereas CGI programs are platform-dependent.

Another difference between servlets and CGI is the maintenance of state information. A servlet maintains memory of its state once it is loaded by the server. The JVM running on the web server loads the servlet when it is called. CGI programs are stateless because they result in the creation of a new process each time a request is serviced.

Servlet Enabling a Web Server

Servers with built-in Servlet Support
A Java-enabled web server is necessary to run Java servlets. Some of the web servers that support servlets include Sun MicrosystemÆs Java Web Server, OÆReillyÆs WebSite, StarNineÆs WebSTAR.

Adding Servlet Support to Existing Web Servers
Third-party server add-ons can be used if your web server does not support servlets. Live Software offers a product called JRun. JRun is a set of classes and native code that can extend several web servers to support servlets. These servers include MicrosoftÆs IIS, NetscapeÆs Enterprise and FastTrack servers, and Apache. Visit Live SoftwareÆs web site for more details at http://www.livesoftware.com/products/jrun/.

Example: Creating a Database Servlet using Data Express

The purpose of this topic is to help you become acquainted with using the Java Servlet API along with using JBuilderÆs Data Express to connect a servlet to a database server. By using the Java Servlet API as the middleware to the database server, users will be able to connect to a database using the HTTP transport. A simple example is used to illustrate the steps on creating this model. There will be three tiers to this model. The first tier is the web browser. The second tier is the servlet implementation, which we will call SimpleServlet. The third tier is the back-end database server.

Following examples will provide illustrations on how to expand the database servlet (SimpleServlet) to be accessible via remote method calls. One example will explain how to expand SimpleServlet to be an RMI server. The other example will explain how to expand SimpleServlet to be a CORBA server. Adding such functionality to SimpleServlet will eventually make the servlet accessible not only through HTTP, but through the RMI, or CORBA transport. The development of these examples will be illustrated using JBuilderÆs built-in RMI and CORBA support respectively.

See also:
Creating distributed applications with CORBA
Distributed computing with Java RMI
Creating a servlet in JBuilder

A Simple Database Servlet
In this chapter, you will build a simple database servlet that will handle requests from client agents to perform a query on a database. The result of the query will be written back to the client in the form of an HTML formatted table. The handling of client requests will be implemented in the servletÆs service() method. The actual database query string will be passed on to the servlet as a servlet parameter named ædbQueryÆ. From this example you will learn how to:

  • Create a servlet using JBuilderÆs Servlet Wizard.
  • Create database objects by using JBuilderÆs Data Express.
  • Implement the servletÆs service() method to obtain the connection to the client agent by using the HttpServletRequest and HttpServletResponse objects, and make a query to the database using the database objects generated by JBuilderÆs Data Express.
  • Implement the init() method in the servlet to open and keep a connection to the database by using the objects generated by JBuilderÆs Data Express.
  • Implement the destroy() method in the servlet to close the connection to the database by using the database objects generated by JBuilderÆs Data Express.
  • Read dataset data results from a database query, format the results into an HTML table, and write results back to the client.

The completed files for this example is in <LOCATION OF SimplServlet>. This directory contains the project named SimpleServlet.jpr and three java files called SimpleServlet.java, IDataTable.java, DataTableImpl.java.

Creating the SimpleServlet in JBuilder
If you are creating a servlet for the first time using JBuilder, you may want to read the section, Creating a servlet in JBuilder. This section walks you through the steps of creating a servlet using JBuilderÆs Servlet Wizard:

  1. Create a new project by selecting File|New Project called SimpleServlet.jpr.
  2. Set the projectÆs classpath to include the Java Servlet API. Select File|Project Properties from the JBuilder menu. If youÆve downloaded JDK1.2, then on the Paths tab, set the Target to the JDK1.2 version. Or if youÆve downloaded Live SoftwareÆs JRun, perform the following steps:
    1. On the Paths tab, click on Add.
    2. In the dialog box, if you have already created a ServletAPI path to run.jar, click on æServletAPIÆ. If you have not created a path to jrun.jar, click New and follow the following steps:
    1. In the Name field, type æServletAPIÆ.
    2. In the Class path field, click on edit.
    3. Click on Add and navigate to <jrun_home>/lib/jrun.jar.
  1. Click Ok all the way through.
  2. Start the JBuilder Servlet Wizard by selecting File|New and then by double clicking the Servlet icon.
  3. On the first page, type in SimpleServlet in the Class field and click on the Generate service() method check box. Click Next.
  4. On the second page, this is where you fill in the properties for ædbQueryÆ. This is the parameter whose value will be the database query string coming from the client. In the field under Name, type in ædbQueryÆ. This name will also have to be agreed upon by the client. Under the Type field, select String. Under the Desc field, you can type any description for the variable you want, or leave it blank. Under the Variable field, type ædbQueryÆ. This is the Java variable name known within the scope of the method handling the request, in this case, the service() method. Under default, if left blank, it will be the empty String. Under Method, select service(). This specifies where the line of code to fetch the ædbQueryÆ value will be generated. Click on Finish.

The generated code should resemble the following:

Example 1-1: SimpleServlet.java
Code generated by JBuilderÆs Servlet Wizard:


package JBExamples.database.servlets.simple;

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

public class SimpleServlet extends HttpServlet 
{
   //Initialize global variables
   public void init(ServletConfig config) throws ServletException
   {
      super.init(config);
   }

   //Service the request
   public void service(HttpServletRequest request, HttpServletResponse   
      response) throws ServletException, IOException 
   {
       String dbQuery = "";

       try { 
          dbQuery = request.getParameter("dbQuery"); 
       } 
       catch (Exception e) {  
           e.printStackTrace(); 
       }
    }

   //Get Servlet information
   public String getServletInfo() 
   {
      return "JBExamples.database.servlets.simple.SimpleServlet Information";
   }
}
For those who are new to servlets, an explanation of the generated code is in order. First lets take a look at what is in between the try/catch clause in the service() method . In here we see the statement request.getParameter("dbQuery"). This fetches the value of the parameter named dbQuery from the client. The request object is of type HttpServletRequest, which is a container of the input stream from the client. This object is passed to the service method from the servlet runner. On the other hand we have the response object. This is of type HttpServletResponse, which is a container of the output stream to the client. The try/catch clause is there to catch any errors that may occur in retrieving the value of dbQuery. If an error occurs, then it will be caught, and the errorÆs stack trace is printed out, generally to a log file. If all goes well in fetching out the value of the dbQuery parameter, then the local variable also named dbQuery will be assigned the query string.

The init method for now contains a single call to the super classeÆs init method, this will later be modified to accomadate the next step, which will involve adding database connectivity functionality.

Adding database functionality to SimpleServlet
If you are new to using JBuilderÆs DataExpress and would like to know more on the details and features of using JBuilderÆs DataExpress. Then you may want to review the section Database Application Developers Guide. The following instructions will walk you through adding database functionality to SimpleServlet using JBuilderÆs DataExpress.

Adding a Database component to SimpleServlet

To add the Database component to SimpleServlet,

  1. Open the Designer by highlighting the Frame file and selecting the Design tab at the bottom of the AppBrowser.
  2. Click the Database component from the Data Access tab of the Component Palette.
  3. Click anywhere on the Component Tree window to add the Database component to your application. This adds the following line of code to your servlet:

Database database1 = new Database();

Setting Database connection properties
For the Database object to be usable, you need to set its connection properties. The ConnectionDescriptor object holds the values to these properties. You can access this object programmatically or set connection properties through the user interface by the following steps:
  1. Select the Database object in the Component Tree. Click beside the connection property in the Inspector window. Click the ellipsis button that appears to open the connection property editor.
  2. Set the following properties:

Property

Description

ConnectionURL

The Universal Resource Locator (URL) of the database, for example,

jdbc:odbc:DemoDatabase.

Username

The user name authorized to access the server database, for example,

SYSDBA.

Password

The password for the authorized user, for example, masterkey.

Prompt user for password

Whether to prompt the user for a Password each time.

Driver Class

The class name of the JDBC driver that corresponds to the URL, for example,

sun.jdbc.odbc.JdbcOdbcDriver

Adding a QueryDataSet component to the SimpleServlet

To add a QueryDataSet component, follow the same steps as with adding a Database component. Once the QueryDataSet has been added set the query properties of the QueryDataSet component from the Inspector as follows:

    • set the query property by clicking on itÆs property value, and selecting the name of your Database component in the Database list box. In our case it would be database1.

Lets try a test query. To do this, type a valid sql query in the SQL statement text box. Click Test Query to ensure that the query is runnable. When the gray area beneath the button indicates Success. Delete the query statement from the text box. For this example we want to dynamically generate the query. In the Create ResourceBundle dialog, select Cancel. For a discussion of this option, see Dissecting the query dialog

The code generated by this step is:

queryDataSet1.setQuery(new borland.sql.dataset.QueryDescriptor(database1, "", null, true, Load.ALL));

SimpleServlet should look something like the following:

Example 1-2: SimpleServlet.java
Code generated by JbuilderÆs DataExpress GUI


package JBExamples.database.servlets.simple;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import borland.sql.dataset.*;

public class SimpleServlet extends HttpServlet 
{
   Database database1 = new Database();
   QueryDataSet queryDataSet1 = new QueryDataSet();

   //Initialize global variables
   public void init(ServletConfig config) throws ServletException
   {
      super.init(config);
   }

   //Service the request
   public void service(HttpServletRequest request, HttpServletResponse 
      response) throws ServletException, IOException
   {
      //A database query
      String dbQuery = "";
      
      try  { 
         dbQuery = request.getParameter("dbQuery"); 
      } 
      catch (Exception e)  { 
         e.printStackTrace(); 
      }
  }

  //Get Servlet information
  public String getServletInfo() 
  {
     return "JBExamples.database.servlets.simple.SimpleServlet Information";
  }

  public SimpleServlet() 
  {
     try {
      jbInit();
     }
     catch (Exception e) {
        e.printStackTrace();
     }
  }

  private void jbInit() throws Exception
  {
     database1.setConnection(new borland.sql.dataset.ConnectionDescriptor(  
     "jdbc:odbc:DemoDatabase",  "",  "",  false,   "sun.jdbc.odbc.JdbcOdbcDriver"));

     queryDataSet1.setQuery(new borland.sql.dataset.QueryDescriptor(database1,  "", 
     null,  true, Load.ALL));
  }

}

Preparing SimpleServlet for multi-threaded situations
LetÆs examine our new SimpleServlet. Basically a constructor with no arguments has been created along with a method called jbInit(). If you are familiar with servlets, you may question the call to jbInit() in the empty constructor. By convention, servlet developers should implement their initialization of data in the servletÆs init method. The init method is called once by the servlet runner when the servlet is loaded to run. On the other hand, the release of resources should be implemented in the servletÆs destroy method. The destroy method is called by the servlet runner when the web server is stopped, or before the servlet is to be reloaded. Because we are dealing with a class of whoÆs entire existence will be within a multi-threaded environment, a few adjustments must also be made for SimpleServlet to handle concurrent database queries correctly. The following code shows the completed SimpleServlet adjusted to handle itÆs database connection correctly.

Example 1-3: SimpleServlet.java
Completed SimpleServlet


package JBExamples.database.servlets.simple;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import borland.sql.dataset.*;

import borland.jbcl.dataset.DataSetException;

public class SimpleServlet extends HttpServlet {
  Database database1 = new Database();

  //Initialize global variables
  public void init(ServletConfig config) throws ServletException{
    super.init(config);

    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

  //Close the database connection
  public void destroy() {
   try {
      System.out.println("SimpleServlet closing database connection.");
      database1.closeConnection();
    }
    catch(DataSetException e) {
      System.out.println("Error in closing the database connection");
    }
  }

  /**
   * Returns a data table containing the results of
   */
  public IDataTable getResultTable(String dbQuery) {
    IDataTable dataTable = null;
    try {
      QueryDataSet queryDataSet = new QueryDataSet();
      queryDataSet.setQuery(new borland.sql.dataset.QueryDescriptor(database1,
      dbQuery, null, true, Load.ALL));

      
      //Query will be executed when QueryDataSet is open
      queryDataSet.open();
      dataTable = new DataTableImpl(queryDataSet);
      queryDataSet.close();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    return dataTable;
  }

  //Service the request
  public void service(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException { //Set content type response.setContentType("text/html"); //A database query String dbQuery = ""; try { dbQuery = request.getParameter("dbQuery"); } catch (Exception e) { e.printStackTrace(); } //Get a result table from the dbQuery IDataTable dataTable = getResultTable(dbQuery); //Get a print stream to the client PrintWriter out = response.getWriter(); //Print out results in html format to the client out.println("<CENTER>");
out.println("<TABLE width=\"80%\" cellpadding=\"0\" border=\"2\"
cellspacing=\"0\">"); out.println("<TR bgcolor=\"#000000\">"); out.println("<TD align=\"center\">");
out.println("<FONT color=\"ffffff\"
face=\"Arial\" size=\"3\"><B>Database Results</B></FONT>");
out.println("</TD>"); out.println("</TR>"); out.println("<TR bgcolor=\"#ffffff\">");
out.println("<TD align=\"center\">"); //Fetch the data in HTML format out.println( dataTable.toHTMLString() ); //Close tags out.println("</TABLE>"); out.println("</TD>"); out.println("</TR>");
out.println("</TABLE>"); out.println("</CENTER>"); } //Get Servlet information public String getServletInfo() { return "JBExamples.database.servlets.simple.SimpleServlet Information"; } /* public SimpleServlet() { try { jbInit(); } catch (Exception e) { e.printStackTrace(); } } */ //Set the database connection private void jbInit() throws Exception{ database1.setConnection(new
borland.sql.dataset.ConnectionDescriptor("jdbc:odbc:DemoDatabase", "",
"", false, "sun.jdbc.odbc.JdbcOdbcDriver")); } }

The Changes to SimpleServlet
The modified, and final SimpleServlet should be all ready to go. Lets compare the differences between the new SimpleServlet with the old one. By making the above changes, SimpleServlet now allows its concurrent threads to use the same database connection, although tying each query to its particular request. If you take a look at SimpleServletÆs empty constructor, it has been commented out. The call to the database initialization jbinit is now called from within the init method. Notice that the class DataQuerySet is no longer an instance variable, and itÆs instantiation has been moved to within the getResultTable method. The setting of DataQuerySetÆs query poperty was cut out of the jbinit method, and placed within the getResultTable method as well. Moving the instance of DataQuerySet confines it to the scope of the getResultTable method. This is to ensure that every concurrent request will be using a unique instance of QueryDataSet, eventually keeping the requests thread safe.

The getResultTable method executes the given query string by simply calling the open method of the QueryDataSet instance. Once opened, the QueryDataSet instance is passed to a constructor of a convenience class DataTableImpl. DataTableImpl is responsible for formatting the query results into an HTML formatted table, or, a tab/newline delimited string.

An implementation of the destroy method has also been added. The destroy method is used to close the database connection.

The service method now has the code to get the results of the database query back to the client. The method call req.setContentType("text/html") tells the client browser to expect html text. This gives the client browser a chance to interpret the data as specified. A stream to the client is obtained by a call to out.getWriter(). A PrintWriter object is returned and eventually used to write the results of the query in an HTML formatted table which is obtained through the method call dataTable.toHTMLString().

The code for DataTableImpl and its interface IDataTable is shown below.

Example 1-4a: DataTableImpl..java


package JBExamples.database.servlets.simple;

import borland.sql.dataset.QueryDataSet;
import borland.jbcl.dataset.DataRow;
import borland.jbcl.dataset.DataSetException;
import java.util.Vector;

public class DataTableImpl implements IDataTable {
/*
 *  A convenience class that copies the data from QueryDataSet
 *  into a table of Strings.
 */
  private String[] columnNames;
  private Vector tableData;
  private int columnCount;
  private int rowCount;

  public DataTableImpl() {
    super();
  }

  public DataTableImpl(QueryDataSet queryDataSet) throws DataSetException
  {
      DataRow dataRow   = new DataRow(queryDataSet);
      this.columnCount  = dataRow.getColumnCount();
      this.rowCount     = queryDataSet.getRowCount();
      this.columnNames  = dataRow.getColumnNames( columnCount );
      copyQueryData(queryDataSet, dataRow);
  }

  private void copyQueryData(QueryDataSet queryDataSet, DataRow dataRow)
    throws DataSetException
  {
    tableData = new Vector();

    for(int i=0; i<rowCount; i++) {
      String[] data = new String[columnCount];
      queryDataSet.getDataRow(i, dataRow);
      for(int j=0; j<columnCount; j++) {
        data[j] = dataRow.format(j);
      }
      tableData.addElement(data);
    }
  }

  public String[] getColumnNames() {
    return this.columnNames;
  }

  public int getRowCount() {
    return this.rowCount;
  }

  public int getColumnCount() {
    return this.columnCount;
  }

  public String getDataAt(int row, int column) {
    return ((String[])tableData.elementAt(row))[column];
  }

  //Return a tab/newline delimited String
  public String toTableString()
  {
    return toTableString("","\n","","\n","","\t");
  }

  //Return an HTML String representation of this object
  public String toHTMLString()
  {
    return toTableString(
       "<table width=\"80%\" height=\"80%\"border=\"1\">",
       "</table>\n","<tr align=center>","</tr>\n","<td>","</td>");
  }

  // Convert the table data of this object to a String using the given table
  // delimiters.
  private String toTableString(String tblStart, String tblEnd, 
    String rowStart, String rowEnd, String dataStart, String dataEnd )
  {
    StringBuffer results = new StringBuffer();

    try {
    results.append(tblStart);
    //Column names
    results.append(rowStart);
    for(int i=0; i"+e.toString();  }

    return results.toString();
  }
}

Example 1-4b: IDataTable.java


package JBExamples.database.servlets.simple;

  public interface IDataTable {
  public String[] getColumnNames();
  public int getRowCount();
  public int getColumnCount();
  public String getDataAt(int row, int column);
  public String toHTMLString();
  public String toTableString();
}

In DataTableImpl, an instance of DataRow is used to get the column names, and the column count of the QueryDataSet object. The row count is obtained from the QueryDataSet object. The method copyQueryData, does just that. It traverses through the QueryDataSet and copies them into a Vector. Each element of the Vector will consist of a String[] containing the data of one row. The row data is obtained from the method call queryDataSet.getDataRow(i, dataRow). This populates dataRow with the data at the specified row i, in queryDataSet. The method call dataRow.format(j) returns the data at the specified column j as a String type.

Right about now you are probably wondering, why we need an interface for DataTableImpl. The reason for this will become clear in the next section when we expand SimpleServlet to be an RMI server.

Invoking SimpleServlet
To invoke SimpleServlet you must first have a servlet capable web server. If your web-server does not support servlets. You can obtain a third party servlet runner plugin for your web server. A product such as Live SoftwareÆs JRun can be obtained at http://www.livesoftware.com/. Once youÆve obtained a servlet runner and installed it, you will have to copy SimpleServletÆs class files into the <servlet_runner_home>/servlets directory.

Note: If youÆve created SimpleServlet within a package, you will have to create your directory structure that maps to the package name under the servlets directory. So if SimpleServlet belonged to a package foo.bar. You will have to create the directory structure foo/bar under the servlets directory, and copy your SimpleServlet class files into the bar directory. In short:


	Class name: foo.bar.SimpleServlet
	Location:     /servlets/foo/bar/SimpleServlet.java
Setting the servlet runnerÆs user classpath
Before the servlet is to be envoked, the servlet runner has to know the location of Borland specific classes. This is done by setting the user classpath in the servlet runnerÆs admin. The Borland specifi class files used in SimpleServlet are in the jar file called jbcl2.0.jar under the <jbuilder_root>/lib directory. The following screen shot illustrates where the path to the jar file should be set in JRunÆs Admin. The field, User Classpath:

In order for this change to take affect, you will have to stop and restart your web server. If this classpath was already specified, there is no need to stop and restart your web server.

Once youÆve done this, the next step is to call the SimpleServlet. Since SimpleServlet handles requests through its service method, you can call SimpleServlet in four popular ways.

  1. through the <servlet> tag
  2. through post
  3. through get
  4. from a java applet

Calling SimpleServlet through the <servlet> tag

Follow the steps to call a servlet with the servlet tag.

  • Create a new file and name it SimpleServlet.shtml
  • Type the following inside the file:

<HTML>

<BODY>

<servlet code=SimpleServlet>

<param name="dbQuery" value="select * from mydatabase">

</servlet>

</BODY>

</HTML>

  • Save the SimpleServlet.shtml into your <web_server_root> directory.
  • Start your web server.
  • Open a browser, and request the SimpleServlet.shtml file.

http://localhost/SimpleServlet.shtml

For cases where you have created SimpleServlet in a package, the full class name is required in the <servlet> tag. So, if SimpleServlet belonged to a package foo.bar, the servlet tag would be <servlet code=foo.bar.SimpleServlet>.

 

Calling SimpleServlet through POST

To call SimpleServlet using post, try the following.

  • Create a new file, and name it SimpleServlet.html
  • Type the following into your file:

<HTML>

<BODY>

<FORM method="post" action="/servlet/SimpleServlet ">

<PRE>

Enter Query: <input type="text" size=80 name="dbQuery">

<input type="submit" value="Execute Query">

</PRE>

</FORM>

</BODY>

</HTML>

  • Save SimpleServlet.html into your <web_server_root> directory
  • In your web browser reguest the page.

http://localhost/SimpleServlet.html

For cases where you have created SimpleServlet in a package, the full class name is required in the <FORM> tag. So, if SimpleServlet belonged to a package foo.bar, the <FORM> tag would be <FORM method="post" action="/servlet/foo.bar.SimpleServlet">.

Calling SimpleServlet through GET

To call SimpleServlet with get, try the following.

  • In your web browser request the page by typing the following.

http://localhost/servlet/SimpleServlet?dbQuery=select+*+from+mydatabase

Note: Just like the prior SimpleServlet calls, the full class name of SimpleServlet is required.

Calling SimpleServlet from an applet

The following class is responsible for connecting to and querying a database servlet.


package JBExamples.database.applets;

import java.util.*;
import java.net.*;
import java.io.*;

public class HTTPTransportClient implements ITransportClient {
  String servletLoc;

  public HTTPTransportClient(String servletLoc) {
    this.servletLoc = servletLoc;
  }

  public String executeQuery(String queryString) throws Exception {
    StringBuffer results = new StringBuffer();

    //The value of dbquery has to be urlencoded to be passed through 
    //http.
    String postData   = "dbquery="+URLEncoder.encode(queryString);

    URL action = new URL(servletLoc);
    URLConnection url = action.openConnection();

    url.setDoInput(true);
    url.setDoOutput(true);
    url.setUseCaches(false);
    url.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
    url.setRequestProperty("Content-length", "" + postData.length());

    // Write out post data
    DataOutputStream out = new DataOutputStream(url.getOutputStream());
    out.writeBytes(postData);
    out.flush();
    out.close();

    // Get response
    DataInputStream in = new DataInputStream(new BufferedInputStream(url.getInputStream()));

    String line;
    while(null != ((line = in.readLine())))
      results.append(line + "\n");

    return results.toString();
  }

}

The executeQuery() method illustrates how to communicate to the JDBC servlet using the HTTP transport. This method also illustrates how general applet to servlet communication can be carried out. A simple test applet in later examples will illustrate using the above class to display the results of a query.

Continue to Part II

Back To Top
Home Page
Trademarks & Copyright © 1998 INPRISE Corporation.