How to get started with server-side Java

Take advantage of the platform-independent, object-oriented power of Netscape's server-side applets. An introduction.

Server-side Java (SSJ), sometimes called servlets or server-side applets, is a powerful hybrid of the Common Gateway Interface (CGI) and lower-level server API programming -- such as NSAPI from Netscape and ISAPI from Microsoft.

This article provides an introduction to and step-by-step instructions for the Netscape implementation of server-side Java, which Netscape calls server-side applets (SSA).

SSAs can act like a CGI script. It receives get and post requests and returns a Web page (usually in the form of HTML), but SSJ is loaded dynamically into the server like NSAPI/ISAPI. This eliminates the start-up delays we've come to expect from CGI. It also allows the SSJ to maintain some of its state between executions, such as keeping an open connection to a database.

SSAs execute in their own sandbox, which provides the security one expects from Java. For example, a crashing applet won't crash the whole server as can happen with NSAPI/ISAPI programming. This added security also allows applets to be uploaded for execution on the server -- just like client-side Java applets are downloaded for execution on the client.

Perhaps the most important aspect of SSAs is that, written in Java, they are inherently platform-independent and object-oriented.

History

A growing number of servers support server-side Java, including the Netscape FastTrack 2.0 and Enterprise 2.0 servers, JavaSoft's Java Web Server (formerly called Jeeves), the World Wide Web Consortium's Jigsaw, WebLogic's T3Server, Oracle's Webserver, and Peak Technologies' ExpressO. Each of these servers uses a different server-side Java API, requiring developers to write different programs for each server they will be using.

Netscape details: Prepare your server

Before authoring your first server-side applet for Netscape's servers, you need to prepare the server. The Enterprise and FastTrack servers are identical in their SSA support.

Start by turning on the server's Java interpreter. This can be done from the Server Manager under "Programs -> Java." Click the Yes button to enable the Java interpreter. The Server Manager will ask you for a "Java applet directory," which is the place to put the SSA support files as well as the location for all SSA class files. It provides a default location. On Unix machines, this is /usr/ns-home/plugins/java/applets. On Windows machines, it is C:\Program&nbspFiles\Netscape\Server\plugins\Java\applets (Note: In this entry field Netscape tends to mix and match its back-slashes and forward-slashes. Don't worry, Netscape treats the two types of slashes in the same way.) Take the default applet directory if possible. If you decide to customize rather than use the default, make sure you choose a directory somewhere under your server root and that you copy all the files from the default location to your custom location. Save and apply your changes, making sure to stop the server and start it again so that the changes take effect.

Time to experiment!

At this point you should be able to experiment with the applets provided by Netscape. Point your browser to http://servername/server-java/FormApplet?abc=xyz&123=789. You should see the "get" data handled and returned in HTML by the Form applet.

If you get a server error, check your server's error log (/usr/ns-home/httpd-hostname/logs/errors or C:\Program&nbspFiles\Netscape\Server\httpd-hostname\logs\errors). If it says it can't start the Java interpreter, a likely cause is that your CLASSPATH is confusing Netscape. Try starting the server in an environment without any CLASSPATH.

Another applet to try is at http://servername/server-java/Connect; it should load and display http://www.meer.net/barn/index.html. The Connect applet establishes a socket connection in order to fetch the page, which may generate a server error if your server is behind a firewall. For the next step, let's assume that a firewall blocked the socket. We'll edit the Connect applet code to access a different page on a different Web server.

The Connect.java file is available in the "Java applet directory." (It is also found below.) It first imports netscape.server.applet.*.

import netscape.server.applet.*;

This package contains the basic classes for developing server-side applets. The most important class in this package is HttpApplet, the superclass for all server-side applets. As you can see in Connect (below), the only method a server-side applet needs to implement is the run method. This method is invoked each time the applet receives a "hit." The run method for Connect opens a socket to the "host" and fetches the "request" before redirecting the output to the client. We want to change the "host" variable so it references a machine visible from our Web server. We'll also want to change the "request" variable so it references a page on the new "host."

import netscape.server.applet.*;
import java.io.PrintStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.DataInputStream;
import java.net.Socket;
class Connect extends HttpApplet {
    public void run() throws Exception {
        String host = "www.meer.net"; // change this
        int port = 80;
        String request = "GET /barn/index.html HTTP/1.0\n"; // this too
        Socket s = new Socket(host, port);
        OutputStream os = s.getOutputStream();
        PrintStream op = new PrintStream(os);
        op.println(request);
        InputStream is = sam();
        DataInputStream di = new DataInputStream(is);
        String line;
        if (returnNormalResponse("text/html")) {
            PrintStream out = getOutputStream();
            out.println("&lth1&gtData on "+host+" port "+port+"</h1>"); 
            out.println("request: "+request+"<hr>");
            while ((line = di.readLine()) != null)
                out.println(line);
        }
    }
}   

After you've made the "host" and "request" changes, the next step is to recompile Connect.

Under Windows, use your standard javac compiler with the classpath set to include serv2_0.zip. javac -classpath ..\classes\serv2_0.zip Connect.java.

Under Unix, Netscape provides a Java compiler (javac) in the directory above the Java applet directory. This javac is actually a script that calls java sun.tools.javac.Main to do the compiling. On some systems the sun.tools.javac.Main compiler uses new 1.1 JDK methods such as java.lang.Character.isJavaLetterOrDigit(), which can cause quite a problem for developers without the 1.1 JDK. A perfectly fine alternative is to use the standard javac compiler you've always used, javac -classpath ../classes/serv2_0.zip Connect.java. If you want to use the provided javac script, just replace "javac" with "../javac."

You may see an error during this compilation that says:

Connect.java:1: Package netscape.server.applet not found in import.
import netscape.server.applet.*;
^
1 error

This error is nothing to worry about. The class file is created normally and will run fine. You can avoid this error if you eliminate wildcards in your import statements.

Under Unix, Netscape provides a makefile in the Java applet directory to handle applet compilation. Unfortunately, the makefile uses the '%' wildcard, which is a mk/nmake extension and is not always available. The problem code is shown below.

%.class: %.java
        ../javac -classpath ../classes/serv2_0.zip $*.java

An alternative is to use a .suffixes rule. Edit the first line of the makefile to be:

.SUFFIXES  : .java .class  
and replace the %.class target lines with
.java.class :
        javac -classpath ../classes/serv2_0.zip $<

You may notice I removed the ../ so that the makefile will invoke the standard javac compiler. To test this new makefile, resave the Connect.java file and try a "make."

If you were to reload the http://servername/server-java/Connect page right now, you would still see the "Barn" page. This is because the Java classes are loaded into the server at start time via an init function in the obj.conf file. To load the new changes, you must stop the server and then start it again. On some systems you must use the Server Manager to do the stop and start. Command-line restarts sometimes result in a "Server Error" for subsequent applet requests. Once you have stopped and started the server, try the Connect applet again. Netscape should have loaded the new Connect code to display the page you selected.

Let's get serious about API

Congratulations! You`ve just compiled and tested your first server-side Java code. Now to give a few of the methods available to you.

With the following methods you can do the majority of your work:

PrintStream getOutputStream() throws IOException;

returns a PrintStream, which you can use to print your response to the client. It replaces System.out.

Hashtable getFormData() throws IOException;

returns a Hashtable storing the name-value pairs of the HTTP request. The value strings are decoded from their URI-encoded form. It throws an IOException if there is no form data.

String getFormField(String fieldName) throws IOException;

You can use getFormField for retrieving just one field. It too throws an IOException if there is no form data.

boolean returnNormalResponse(String contentType) throws IOException;

starts an HTTP response with the content type set as you specify with its parameter. It returns true if this was a "get" or "post" request and false if it was a "head" request.

public boolean returnErrorResponse(String contentType,
                                   int status,
                                   String reason) throws IOException
public boolean returnErrorResponse(String contentType,
                                   int status) throws IOException

starts an HTTP response to report an error. It takes a content type, a status (such as HttpApplet.BAD_REQUEST, which represents the standard error code 400), and an optional string giving the reason for the error.

There are dozens of other methods you can use in the development of your server-side applets. Netscape installs an API guide with its servers. You can find the guide at /usr/ns-home/bin/httpd/admin/html/manual/pg/javapi.htm under Unix or at C:\Program&nbspFiles\Netscape\Server\bin\httpd\admin\html\manual\pg\javapi.htm under Windows.

Hello World!

Now let's use everything we've learned to write the (you guessed it!) Hello World server-side applet. The following applet says hello to World unless a target field is given -- in which case it says hello to the target instead.

import netscape.server.applet.HttpApplet;
import java.io.IOException;
import java.io.PrintStream;
class Hello extends HttpApplet {
  /* By default, we say hello to "World"
  */
  String helloTarget = "World";
  /* run() is invoked to handle the request
  */
  public void run() throws Exception {
    /* getOutputStream() allows us to talk to the client
    */
    PrintStream out = getOutputStream();
    /* Use getFormField() to find out if we are to say hello to
     * someone other than "World".
    */
    String formTarget = null;
    try {
      formTarget = getFormField("target");
      if (formTarget != null) {
        helloTarget = formTarget;
      }
    }
    catch (IOException e) {
      /* We'll ignore exceptions caused by a "missing query string"
      */
      if (! e.getMessage().startsWith("missing query string")) {
        handleException(e, out);
      }
    }
    /* Say the hello
    */
    if (returnNormalResponse("text/html")) {
      try {
        out.println("Hello, " + helloTarget + "!");
      }
      catch (Exception e) {
        handleException(e, out);
      }
    }
  }
  private void handleException(Exception e, PrintStream out) {
    try {
      returnErrorResponse("text/html", SERVER_ERROR, "Exception thrown");
    }
    catch (IOException ioe) {}  // try to print original exception
    out.print("&lth1>");
    out.print(e);
    out.print("</h1>\n");
    out.print("&ltpre>");
    e.printStackTrace(out);  // alternative PrintStream must be specified
    out.print("</pre>");
    return;
  }
}

This server-side applet subclasses from netscape.server.applet.HttpApplet and overrides the run() method just like all server-side applets under Netscape. It quickly gets its output stream with a call to getOutputStream, which it will use to print the "Hello" (or use to print the reason for a failure). It calls getFormField to check if there is an alternative target to use, and then returns a normal "text/html" response, and finally does the actual work of printing "Hello." Notice that it checks the return value from the returnNormalResponse() call and does nothing if it returns false. If you do not do this, you will return data even for head requests.

Including your own classes

The classpath for server-side applets is stored in the Netscape server's obj.conf file, available in the admserv directory under your server root. If you want to use classes that aren't found in serv2_0.zip (such as JDBC driver classes), you will have to edit the obj.conf file. On Unix, this probably will require root access. In the obj.conf file, there is a line that says classpath=/usr/ns-home/plugins/java/classes/serv2_0.zip. The full path of any foreign classes should be appended to this line. Then, to apply your changes, in the Server Manager click on Apply in the upper right-hand corner. And, as always, you'll need to stop and start the server before these changes will take effect.

Next time

Server-side Java is a powerful new technology but one that needs a well-documented standard. This article should help you get started using SSJ with the Netscape servers. In future months I will expand on this base to discuss in more detail the netscape.server.applet classes, how to return multipart responses, tricks for accessing databases, and synchronization issues.

Jason Hunter works in software testing at Silicon Graphics Inc., where he breaks all sorts of pre-release Web technologies. He has jumped on the Java bandwagon and is busy using it to aid in automated testing across multiple platforms. If by some miracle you don't find him at work, he's probably out hiking in the mountains.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more