Using Java, Java Servlets and JSP for web development

Note

None of the servlet examples are accessible, so all of the links just point to the source code. The source for the applets may be found here and the source for the servlets here.

I haven't had time to put in all I want, but those sections will be updated at some point.

Introduction

This is not a tutorial on how to use Java; rather it is a collection of examples and references to show the capabilities of this technology and where to find out more information. For some excellent tutorials (and more examples) look in the Reference section.

Java is your one-stop shop for creating interactive web content; you can use it both for client side programming in applets that run in the web browser, and for server side programming to create dynamic web content. It is not, however, the ultimate panacea since it can be rather heavyweight for a simple web form and many browsers do not support it or have buggy implementations.

I shall first discuss how to install the necessary tools and then present (in order) servlets, applets and Java Server Pages (JSP). Servlets run on the web server and using them often require access to the server itself. However, with a correctly setup server this need not be the case.

To do this yourself you will need:

Security: If you are at all concerned about security, then you should also install mod_ssl to provide a secure sockets layer implementation for your web server.

Installation

If you have an rpm-based system, then you can find rpms for all of the above at rpmfind.net if they were not included with your distribution. Versions change so I won't bother to list the exact files. Most of these work surprisingly well straight out of the box, but I strongly recommend downloading the sources for Apache, mod_ssl, ApacheJServ and Tomcat, and compiling them yourself. That way you can ensure that the various Java class libraries and other components are in sync. The instructions for compiling these are straightforward and I've summarized my own experiences in Appendix A.

Harder to figure out are some of the configuration files. The rough outline is as follows:

Apache/ApacheJServ

Tomcat

To be done ...

Postgresql

This mostly works straight out of the box, but you should at least look at the access control file /usr/lib/pgsql/pg_hba.conf. In order to use this with the JDBC classes you will need to create a database, say "servletDB" and you must run the backend process, postmaster, with the "-i" flag. More on this when we actually use it.

Apache

Apache configuration is a whole subject in itself, but somewhere in the main configuration file httpd.conf you should have lines:

# at the top of the load module section
LoadModule jserv_module	      libexec/mod_jserv.so

# At the top of the AddModule section
AddModule mod_jserv.c  

# Include the jserv config file
<IfModule mod_jserv.c>
             Include conf/jserv/jserv.conf
</IfModule>
You should also install mod_ssl to enable secure sockets communication with the web server. Make sure that you compile apache (and modules) with -DEAPI.

ApacheJServ

jserv.conf

The main config file is conf/jserv/jserv.conf. Most of the defaults are fine. Note the name of the properties file, something like conf/jserv/jserv.properties, the log file logs/mod_jserv.log and the servlet zone specified with the directive:
ApJServMount /servlet /root
This means that servlets referenced by http://host:port/servlet/MyServlet will take their properties from the zone "root".

jserv.properties

Properties for the Java VM. Important parameters:

# Where to find java
wrapper.bin=/usr/local/jdk1.2.2/bin/java

# Classpath values
wrapper.classpath=/usr/local/apache/libexec/ApacheJServ.jar
wrapper.classpath=/usr/lib/pgsql/jdbc7.0-1.2.jar
wrapper.classpath=/usr/local/jdk1.2.2/jswdk-1.0.1/lib/servlet.jar

# Servlet zones
zones=root

# Properties file for each zone
root.properties=<server-root>/conf/jserv/zone.properties
check to see that the logging is set up as well.

zone.properties


# Where to find the servlets
repositories=<server-root>/servlets
Here you can set initial parameters for each servlet and make aliases for servlets. I will talk about these in more detail when we use them.

Applets

Applets run in the web browser - they are client side applications that the browser downloads from the server and then executes locally. In order to run them you have to have a browser that supports Java, but they need no support from the server.

The basic idea of writing an applet is to write a class that extends java.applet.Applet and implement the methods public void init() to set up your applet, public void start() to start any actions running that you need and public void stop() to stop anything you have started. You must then write an HTML page that contains an <applet ... > tag telling the browser where to find the applet.

The simple applet HelloWorldApplet displays an image containing "Hello World". Here's the source code. It doesn't do anything but sit in the browser window so all it needs to implement is the init() method.

A little more interesting is BouncingTextApplet which displays some text bouncing around the display. Here's the source code.

The init() method sets up the user interface - this consists of getting the text and measuring it, creating Start and Stop buttons (these just execute the start() and stop() methods) and getting an off-screen area to draw on so that we can have flicker-free animation.

The animation needs to run in a separate thread in order to let the browser have some control over the applet, so the start() method starts the animation thread, while the stop() method stops it. The bulk of the work is done by the run() method which moves the text aroud and the paint() method that draws it.

The last example of an applet, before we talk about servlets, is an SSH client written as a Java applet. It has a complete terminal emulation inteface that allows you to make an SSH connection and then use it as a standard terminal window - so you may run things like pine and emacs and so on, even lynx! It has all the standard VT100 features. There is one small problem: because of security restrictions you can only connect back to the host from which you downloaded the applet, so you must have a shell account on that host. However, suppose you have a shell account on MLUG. Then you can copy these classes to your public_html directory and connect to MLUG via any Java enabled web browser. This can be very convenient if you end up in BFE with only a windoze machine and no ssh client to check your email. It can also be used for remote administration of your own machine if you are running a web server.

Servlets

Getting Started

Once you have the ApacheJServ engine installed you can start it simply by restarting apache. Servlet classes belong under the directory <server-root>/servlets/. The HelloWorldServlet is about as simple as you can get. You need to copy HelloWorldServlet.class to <server-root>/servlets/ and then call it with the URL http://host:port/servlet/HelloWorldServlet

The next example rob.servlets.TestServlet belongs to the package "rob.servlets" (note the declaration "package rob.servlets ;" at the beginning of the source file). The class file must be placed in the directory <server-root>/servlets/rob/servlets/ and it is called with URL http://host:port/servlet/rob.servlets.TestServlet

This servlet shows all the information that is available to the servlets when a request is made. The parameters heading is for any additional parameters that were passed in to the servlet with the request. For example if you call the servlet as http://host:port/servlet/rob.servlets.TestServlet?name=value then you will see this listed.

Servlets may be called from HTML pages using either an anchor (which will send a GET request) or a form which can send both GET and POST requests. The page exampleForm.html calls TestServlet with all three methods.

Writing a Servlet

All you must do in order to write a useful servlet is implement either of the methods doGet or doPost:

	public void doGet(HttpServletRequest req, HttpServletResponse res)
	    throws ServletException, IOException 
	public void doPost(HttpServletRequest req, HttpServletResponse res)
	    throws ServletException, IOException
If you don't care about the difference between GET and POST requests, then you can just implement one, say doGet and then set the other to call it:


    public void doPost(HttpServletRequest req, HttpServletResponse res)
    	throws ServletException, IOException {
	doGet(req, res) ;
    }
I only usually bother implementing doPost if the data sent with the request is more than just "name=value" pairs from a form - for example a file, or a Java Object sent from an applet.

GET and POST requests

A few notes may be in order on GET and POST requests. When a browser requests a URL from a web server, for example when you click on a hyperlink, it typically sends a GET request that looks like, "GET /servlet/HelloWorldServlet HTTP/1.0". If extra parameters are required, then they are transmitted in the form "x-www-form-urlencoded". Spaces are changed to '+', A-Z, a-z, 0-9 are unchanged and all other characters are converted into the 3-character string "%xy", where xy is the two-digit hexadecimal representation of the lower 8-bits of the character.

Suppose you have a form:


<form action=/servlet/rob.servlets.TestServlet method=get>
<input type=text name=textfield>
<input type=hidden name=action value=test
<input type=submit>
</from>
If someone types in "Some text @$#" and clicks the submit button, then the browser will send the request as /servlet/rob.servlets.TestServlet?textfield=Some+text+%40%24%23&action=test This has the base URL, then a '?' and finally the encoded parameters as name=value separated by '&' symbols.

When you receive the response this is exactly what you will see in the browser's URL line.

You can achieve the same request using an anchor: /servlet/rob.servlets.TestServlet?textfield=Some+text+%40%24%23&action=test.

So much for GET requests. If instead the form had said "method=post" in the first line, then the browser would have sent the request as POST /servlet/rob.servlets.TestServlet HTTP/1.0 and then sent the form parameters as a stream of data (still with the same encoding). This is useful if you need to send more data than a GET request can handle, or if you want to send data other than "name=value" pairs.

In case the encoding sounds complicated, you don't have to worry about it. The servlet engine decodes it all and has several methods for you to query the parameters.

Initializing a Servlet

TestServlet is a simple servlet to demonstrate loading initial parameters and the information available from the request.

The first thing TestServlet does is read initial parameters. The most common use of these are to pass in database information. A servlet also has access to the local filesystem (although typically the servlet engine runs as user "nobody" so files must be world readable for the servlet to read them). Thus, you may also store information in a file that the servlet can read.

When a request is made for TestServlet it reads any parameters sent with the request, eg /servlet/rob.servlets.TestServlet?name=rob will have a parameter of name = rob. Then it queries both the request and the servlet engine for all the information it stores. The reaults are then returned in a web page.

BouncingTextServlet

rob.servlets.BouncingTextServlet is a silly servlet that allows you to send some text as a parameter, and then it returns the BouncingTextApplet with the text you gave it.

Call it with /servlet/rob.servlets.BouncingTextServlet?text=value, but you have to make sure that you encode value properly, otherwise some of it may get lost.

SSHServlet

SSHServlet manages to be both very simple and too complicated, so is perhaps not the best example. However, it shows both how to maintain state using cookies and URL re-writing, and also why serlvets, or something similar, are essential to certain applications.

This servlet opens an SSH connection to the local host and keeps it running until the user requests that it stop. In order to do this the servlet engine has to hold the network connection open itself - something that would be impossible in a regular CGI script which runs and then terminates.

This example uses the same SSH classes from mindbright that the SSH applet used, but it would be perfectly possible to have written this servlet to create a local ssh process instead, and talk to that directly.

AddressBookServlet

AddressBookServlet is a very simple addressbook, but it demonstrates how to interact with a database using a servlet, and also how to maintain state using cookies.

More Applets

AddressBookApplet is the applet version of AddressBookServlet. It uses a very similar servlet - in fact a subclass - to get the data from the database, but it deals with the presentation itself.

Advantages: less work in writing and returning HTML pages; lower network bandwidth because only the data needs to be transfered, not the whole page.

Disadvantages: more work to set up the applet to display the information and write its GUI; no security in that the applet can't use the browser's SSL connection, but has to create its own network connection.

The second disadvantage is not necessarily bad in that it is easy to add encryption into the applet's network connection, but I don't have any examples that I can show of this right now.

A cool applet by Ryan Thornton (hope this is okay for me to link to it, Ryan).

JSP

Java Server Pages (JSP) are Sun's answer to Microsoft's Active Server Pages (ASP). To use them requires more than ApacheJServ: one has to upgrade to the Apache/Jakarta project's Tomcat servlet engine. This will work out of the box as a stand-alone web server and servlet/JSP engine, but configuring it to work with Apache takes a little more effort. When I have more time I'll add some notes on how to do that.

The principle behind JSP is like that of PHP and ASP pages. The server recognises that it is being asked to return a JSP page and sends it to the JSP engine (Tomcat). Tomcat processes the page and returns the HTML generated. A JSP page may contain any valid HTML together with fragments of Java code. A quick reference for the tags may be found here: http://java.sun.com/products/jsp/tags/11/syntaxref11.html.

JSP are best illustrated by examples (taken from the O'Reilly Servlets book).

The Scriptlet Tag

Include arbitrary Java code in a file by putting it between tags
<% code fragment %>

Hello World version 1.


<HTML>
<HEAD><TITLE>Hello</TITLE></HEAD>
<BODY>
<H1> 
<%
if (request.getParameter("name") == null) {
   out.println("Hello World");
} 
else {
  out.println("Hello, " + request.getParameter("name"));
}
%>
</H1>
</BODY></HTML>

The Expression Tag

Include Java code that produces a text output with
<%= code fragment %>
The previous example can be re-written: Hello World version 2.

<HTML>
<HEAD><TITLE>Hello</TITLE></HEAD>
<BODY>
<H1> 
<% if (request.getParameter("name") == null) { %>
Hello World
<% } else { %>
Hello, <%= request.getParameter("name") %>
<% } %>
</H1>
</BODY></HTML>
Notice that the scriptlet may be broken by HTML.

The Declaration Tag

This allows you to declare (define) arbitrary Java fields and methods with
<%! declaration %>

The difference between this and scriptlets is that scriptlets are executed as the page is processed and can result in text being output, or simply cause some text to be written instead of another text. Declarations are stored and may be called or referred to later. Here is a third version of the same thing: Hello World version 3.


<HTML>
<HEAD><TITLE>Hello</TITLE></HEAD>
<BODY>

<%!
private static final String DEFAULT_NAME = "World!";

private String getName(HttpServletRequest req) {
  String name = req.getParameter("name");
  if (name == null)
    return DEFAULT_NAME;
  else
    return name;
}
%>

<H1>
Hello, <%= getName(request) %>
</H1>
</BODY>
</HTML>

The Include Directive

This includes a static file in a JSP file, parsing the file's JSP elements.
<%@ include file="relativeURL" %>

There's not much to say about this one - it is directly equivalent to PHP's include statement and just dumps in the text from the file (or the text after processing if it is another JSP file.

The Page Directive

This may be used to control various properties of the return page. Probably the most common use is to import Java classes:
<%@ page import="java.util.*, java.lang.*" %>

Using Java Beans

At their most simplistic Java Beans are classes whose fields may be manipulated with a fixed API. What do I mean? Suppose you have a class called Name that contains the field private String name. Then the Bean will allow you to get and set the "name" property with the methods

public void setName(String s) 
public String getName() 
You can use these classes in your JSP page in a transparent manner. Here is a simple Bean with a property "name":

public class HelloBean {

  private String name = "World";

  public void setName(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }
}
If you call this class "HelloBean.java", compile it and put it in Tomcat's classpath, then you can use it with the <jsp:useBean ... > tag, and get/set its properties with the tags

<jsp:getProperty name="HelloBean"  property="name" />
<jsp:setProperty name="HelloBean" property="name" value="Rob" />
Actually setProperty is smarter than that - if the request contains the property "name", then you can set the corresponding property in the bean with

<jsp:setProperty name="hello" property="name" />

The "Hello World" page again: Hello World version 4.


<%@ page import = "HelloBean" %>

<jsp:useBean id="hello" beanName="HelloBean" type="HelloBean" scope="request" />
<jsp:setProperty name="hello" property="name" />

<HTML>
<HEAD><TITLE>Hello</TITLE></HEAD>
<BODY>
<H1> 
Hello, <%= hello.getName() %>
</H1>
</BODY>
</HTML>

References

Books

Relevant O'Reilly books:

Resources on the web

http://java.sun.com/j2ee/tutorial/doc/JSPIntro.html

Appendix A: Compiling apache and modules

Not done yet ...

Fri Apr 20 16:33:39 CDT 2001