Deploying Java Applets
by Eric Giguere
This document, written in 1998,
discusses how to deploy your Java applets. Although it was
written a few years ago, the information it conveys is still
valid today. Read it and you should end up with a good understanding
of how applet deployment works.
At some point I will revise the material to
include a full discussion of the Java Plug-in and
to remove all references to PowerJ, the Java development
tool I was working on at the time I wrote this.
1. Web Servers and Web Clients
The key to understanding applet deployment is to understand web servers and
web clients (a web browser is a type of web client, and we'll use the two
terms interchangeably).
A web server is an application that runs on a machine connected to the
internet or the company intranet (we'll refer to it as the web server machine).
Its sole purpose is to listen patiently for connection requests from web server
clients. The web server creates a TCP/IP port (port 80 is the default, although
you can configure a web server to use a different port number) and services
incoming connections.
The basic transaction between a web client and a web server works as
follows:
- Client initiates a TCP/IP connection to the server.
- Client sends its request.
- Server process request and sends a result.
- Client terminates the TCP/IP connection.
A key concept here is that the client-to-server communication is a
stateless communication the web client initiates a
new connection each
time it makes a request instead of keeping a single connection open.
The web
server doesn't keep track of individual clients, it merely services the requests
as they come in and then "forgets" about them. This keeps network congestion
down and allows the server to process many more requests from clients. If you
want the server to remember who you are, you have to pass it some kind of
"session" information browsers use cookies to do this, for example
so that it "remembers" who you are from one connection to the next.
Clients make requests to the server using a simple, partly text-based
protocol called HTTP. The most common request is to GET a file:
GET /products/powerj/index.html HTTP/1.0
|
The client sends the GET command, an absolute path to a file and the HTTP
protocol version it supports (the server uses this information to tailor its
response to the client). In the simplest scenario the web server simply fetches
the requested file and returns it to the client. The client can send extra
information along with the GET (on separate lines), such as the type of client
(so the server knows if it's talking to a Netscape or a Microsoft browser, for
example), cookies (for session information), and what kind of data it can accept
back in response from the server.
An important thing to remember is that the server always deals with absolute
paths, never relative paths. The client is responsible for converting relative
path information to absolute paths before making a request. This has important
implications for applet deployment, as we'll see later.
The web server is free to interpret the path the client sends it as it sees
fit, of course. Usually there is a simple mapping onto the file system. For
example, the root of the path might be mapped to c:\html, in which case the
path
/products/powerj/index.html
|
would map to
c:\html\products\powerj\index.html
|
The mapping is configured by the web server administrator (the
webmaster). Multiple mappings are possible with most web servers, so for
example you might have mappings like this:
- / maps to c:\html
- /scripts maps to d:\util\scripts
- /products/powerj maps to c:\productinfo\powerj
Thus the paths:
/products/index.html
/scripts/foo.pl
/products/powerj/index.html
|
would map to:
c:\html\products\index.html
d:\util\scripts\foo.pl
c:\productinfo\powerj\index.html
|
As you can see, interpretation of what a path means is completely up to the
web server. Often, paths map directly to the filesystem. Sometimes
they map into database entries.
Other mappings may allow the web server to invoke extension programs
(either as DLLs or as executables) to process the client's request whenever
special processing is required.
After interpreting the request, the server sends back a response code, a MIME
type, and a stream of bytes. The MIME type (for example, text/plain) tells the
client how to interpret the stream of bytes coming back from the server.
2. How Browsers Work
As mentioned before, a browser is a type of web client, by far the most
common type of web client. The browser deals primarily with HTML, a kind of
tagged text. The tags describe either the structure of the document or the
formatting to apply. The browser interprets these tags to format the text.
Let's walk through the typical use of a browser:
1. The user types in a URL describing the data to display. URL stands for
Uniform Resource Locator and is a standard way of specifying where and how to
get a "resource" a text file, image, movie, etc. The URL might be:
http://www.sybase.com/products/powerj/index.html
|
The first part, the "http://", tells the browser that it has to use the HTTP
protocol when talking to the given server. The rest of the syntax depends on the
protocol being used. In this case "www.sybase.com" locates the web server
machine and the "/products/powerj/index.html" is the absolute path of the file
to fetch on that machine.
2. The browser opens a connection to http://www.sybase.com/ at port 80 (the port
number is assumed since it wasn't specified).
3. The browser sends the request:
GET /products/powerj/index.html HTTP/1.0
|
to the server.
4. The server returns the file, say it's text like this:
<html>
<body>
<img src="gif/powerj_logo.gif" height=50 width=200>
<h1>Sybase PowerJ</h1>
PowerJ is a great Java development tool!
<p>
Return to the <a href="/index.html">main Sybase page</a>.
</body>
</head>
|
The connection to the web server is severed after the file is sent.
5. The browser begins processing the text (actually, it usually starts
processing the text as soon as it arrives instead of waiting for the connection
to end), looking for tags. The <html> tag indicates this is an HTML
document, and the <body> tag indicates the start of the body of the page.
The first tag in the body is the <img> tag, which indicates that an image
should be displayed at the current page location. The attributes in the tag give
a URL for the image and its expected height and width.
6. The browser starts downloading the image in the background. It forms a
second URL from the URL of the page and the relative path of the image:
"http://www.sybase.com/products/powerj/index.html" and "gif/powerj_logo.gif"
combine to form "http://www.sybase.com/products/powerj/gif/powerj_logo.gif". It
connects to the server and sends
GET /products/powerj/gif/powerj_logo.gif HTTP/1.0
|
and waits for the image to be sent back from the server.
7. Meanwhile, the browser continues processing the page, having reserved
space for the image. It changes to larger, bolded fonts and puts out the heading
(between the <h1> and </h1> tags), switches back to the normal font
and displays the two paragraphs of text (separated by the <p> tag). The
second paragraph includes a link to a second page, denoted by the <a> and
</a> tags.
8. At some point the image finishes downloading, the second connection to the
server is terminated and the image is displayed.
The page display is complete and all communication with the web server has
stopped. If the user clicks on the link, the URL
"http://www.sybase.com/index.html" is formed and the process starts all over
again.
Note how every image, sound, etc. turns into another GET from the web server.
This will apply to applets as well, as we'll see below. (From a technological
point of view, a browser is much more complicated to write than a web server. At
its most basic, a
web server mostly serves up files and only needs to support a few operations. A browser
must be able to fetch files from servers using a variety of protocols, display
or play images, sounds and movies in a variety of formats, process HTML tags,
etc.)
3. Browsers and Java
Some browsers can run Java applets. They do this by having a full-fledged
Java interpreter built right into the browser or loaded as a browser
extension (or plug-in).
Note that the Java interpreter used by the browser may or may not respect the
settings of the CLASSPATH environment variable, depending on which browser
you're using. This can affect what happens when you download applets.
A Java applet is embedded in an HTML page using the <applet> tag, as
in:
<applet code="main.class" height="100" width="100"></applet>
|
When the browser sees this tag, it does the following:
- Starts the Java interpreter if it's not already running.
- Reserves the given amount of space (100x100) on the page and creates a
Java container in that space.
- Downloads the file main.class (we'll discuss this more below) and makes
sure it extends java.applet.Applet (which itself extends java.awt.Panel). The
downloading is done using a simple GET request, much like an image is
downloaded.
- Adds the applet as a child of the container.
- Calls the init() method on the applet, then the show() method.
The tricky part in all of this is the downloading of the class file or files
that define the applet: the key to understanding applet downloading is to
remember that all downloading is done using GET requests to a web server, and
that the browser can only send absolute path requests to the web server. To
successfully load an applet, you must configure both the web server and the
APPLET tag so that the browser will be able to retrieve each file required by
the program.
Note: Browsers will not download (for security reasons) any classes whose
package name starts with "java.". In other words, if your applet depends on
java.awt.event.ActionListener, an interface introduced in Java 1.1, and
your browser only supports Java 1.02, then your applet will not load in that
browser no matter what files you put on the web server. (There are some
techniques you can use, however, to make an applet "degrade" gracefully when
running under Java 1.02 while still making use of features in Java 1.1 for
browsers that support it. These are described on the Sun website at
http://java.sun.com/products/jdk/1.1/compatible/index.html.)
4. Understanding the APPLET Tag
The applet tag has four main purposes:
- It lets you specify the "main" class of an applet using the CODE=
attribute. The "main" class is the class that extends java.applet.Applet.
- It lets you specify the "code base" of the applet using the CODEBASE=
attribute. The "code base" is the root directory that the browser will use to
form GET requests for particular files.
- It lets you specify a width and height for the applet using the WIDTH= and
HEIGHT= attributes.
- It lets you pass parameters to the applet using the <PARAM>
tags.
The first two items are the ones that really interest us, the CODE and
CODEBASE attributes, since these are the two that get the applet from the web
server onto the browser.
Let's start with the CODEBASE attribute. It specifies the root directory for
the Java class files. If it's missing, then "CODEBASE=." is implied, which means
that the root directory is the directory that the HTML file came from. This may
make more sense with a few examples:
- HTML file http://www.sybase.com/index.html, CODEBASE=., root directory is
http://www.sybase.com/
- HTML file http://www.sybase.com/products/powerj.html, CODEBASE=../, root
directory is http://www.sybase.com/products
- HTML file http://www.sybase.com/products/powerj.html, CODEBASE=/java, root
directory is http://www.sybase.com/java
- HTML file http://www.sybase.com/products/powerj.html,
CODEBASE=http://java.sun.com/applets, root directory is
http://java.sun.com/applets
The last example shows you that you can actually set the codebase to point to
a completely different web server, which means that your HTML pages can refer to
applets that you didn't even write. This, however, has important security
implications because untrusted applets are only allowed to connect to the host from which
they were downloaded (as opposed to the host that the HTML page came from)
keep this in mind if you're connecting to databases.
The root directory determines which server the GET requests for the applet
files are sent to and is used to form the absolute paths for each file. Say the
applet tag is:
<applet code="main.class" codebase="/java" height="100" width="100"></applet>
|
and the HTML file came from http://www.sybase.com/index.html. The browser
will then send the following GET request to www.sybase.com:
GET /java/main.class HTTP/1.0
|
Say the "main.class" file requires "Form1.class" to run. The browser would
then send the request:
GET /java/Form1.class HTTP/1.0
|
to the server to fetch that file. This continues until all the files that the
applet requires are fetched. If an applet depends on a class that has a package
name, say powersoft.powerj.ui.ResizePercentLayout, then the GET request looks
like this:
GET /java/powersoft/powerj/ui/ResizePercentLayout.class HTTP/1.0
|
In other words, the full package name of the class is used, but with the "."
characters replaced with "/" characters to form a path (and ".class" is then
appended). So when you put .class files on your web server you have to make sure
that the directory structure reflects the package structure of the classes.
Remember as well that case matters in Java and on some filesystems (such as
Unix or Linux)!
Note that your applet won't run if any of the files that it requires are
missing. You will usually see a message in the browser's status area about this,
and you can use the browser's Java console (which we'll discuss later) to
discover which class is missing. Sometimes this message appears after your
applet starts running, because browsers only download class files as they're
needed by the interpreter, and the interpreter only needs them when objects are
created or static members are used/invoked.
5. ZIPs, CABs and JARs
One problem with Java applet downloading is that each class file is fetched
using a separate GET request back to the web server. There is a lot of overhead
involved in making and terminating connections to the web server, so a
complicated applet with more than just a few class files can take quite a while
to download. This is where ZIP, CAB and JAR files come into play.
The idea is quite simple: instead of individually downloading class files,
package them up into a single file, download them, and then unpack the files on
the client side. Only one connection back to the server is required, and by
using compression you can reduce the size of the file to be downloaded.
Unfortunately, how you do this depends on which browser you're using!
However, the concept in all cases is the same: a tool is used to package a set
of Java class files into a single file for download by the browser and the
<APPLET> tag is modified to refer to that file.
To support Netscape browsers 3.x and above you use the uncompressed ZIP
format (built using PKZIP or WinZip) and the ARCHIVE tag in an applet, as
in:
<applet code="main.class" codebase="/java" width="100" height="100" archive="applet.zip">
</applet>
|
If the HTML page came from http://www.sybase.com/index.html, then this would
turn into a GET request of the form:
GET /java/applet.zip HTTP/1.0
|
To support IE 3.x and above you use the CAB format (build using Microsoft's
CAB development package) and a special "cabbase" parameter:
<applet code=main.class codebase=/java width=100 height=100>
<param name=cabbase value=applet.cab>
</applet>
|
This would make the request:
GET /java/applet.cab HTTP/1.0
|
The contents of the CAB are compressed and can be digitally signed.
To support Java 1.1-enabled browsers (Netscape 4.x with patches, IE 4.x,
HotJava, etc.) you can also use the JAR format, which is basically a compressed
ZIP file:
<applet code="main.class" codebase="/java" width="100" height="100" archive="applet.jar">
</applet>
|
Just as with the ZIP file, this would make the request:
GET /java/applet.jar HTTP/1.0
|
JAR files are built using the jar tool that comes with Sun's Java development
kit. JAR files can also include digital signature information.
Note that if you use the ARCHIVE= attribute you can specify multiple ZIP/JAR
files as in:
<applet code="main.class" codebase="/java" width="100" height="100"
archive="applet.zip,powerj.zip">
</applet>
|
However, the Netscape browsers currently only download the first ZIP/JAR
file, whereas IE 4.x will download them all. Similarly, you can do the same
thing for CAB files:
<applet code="main.class" codebase="/java" width="100" height="100">
<param name="cabbase" value="applet.cab,powerj.cab">
</applet>
|
Note that if you want to cover all the bases, you can actually specify both
ZIP and CAB files in the same applet tag:
<applet code="main.class" codebase="/java" width="100" height="100" archive="applet.zip">
<param name="cabbase" value="applet.cab">
</applet>
|
Internet Explorer will ignore the ARCHIVE= tag in favour of the "cabbase"
parameter and Netscape will use the ARCHIVE= tag (and pass the "cabbase"
parameter to the applet, so be prepared to ignore it if your applet has to
process parameters).
If a given class can't be found in an archive, or else if no archives are
supported, the browser will simply ask the web server for the individual class
files based on the CODEBASE, so you can actually cover all the bases by putting
ZIP, CAB and class files up on the server (see below).
So what really happens inside the browser? When the browser processes the
APPLET tag and notices that ZIP/CAB/JAR files are referenced, it requests the
files from the web server, adds the contents of the files (uncompressing if
necessary) to its internal CLASSPATH, and then goes about trying to run the
applet.
6. Installing Applets On Your Web Server
Now that you understand how applet downloading works, you can easily install
applets on your web server with a minimum of fuss. First you figure out how you
want to package your applet:
- If your applet is Java 1.1 based, package it as a JAR file (in PowerJ you
simply add a JAR target to your project and make it depend on the applet
target).
- If your applet is Java 1.02 based, package it as a ZIP file to target
Netscape browsers and/or as a CAB file to target IE (in PowerJ, add the ZIP
and/or CAB target to your project and make it/them depend on the applet
target).
- If your applet is Java 1.02 based and you want to target the maximum
number of browsers, you'll also want to put the individual .class files on your
web server (in PowerJ, add a Web Application target and make it depend on the
applet target).
Second, figure out what other pieces have to be included with your applet.
For example, if your applet uses any of the classes in the PowerJ class library
(the ones whose package name starts with "powersoft.") then you'll have to
include those with the applet. Similarly, if your applet uses does any database
access you'll have to include the appropriate JDBC driver classes.
How you include those extra pieces depends on how you're packaging your
applet. You can, for example, combine everything together into a single
JAR/ZIP/CAB file, or you can keep them as separate files. The JAR/ZIP/CAB
targets in PowerJ can automatically package up all the necessary files with
one important exception for you if you want. The exception is that classes
that are dynamically loaded (JDBC drivers being the most common example) are not
caught by this process.
The third step is to actually place all the necessary files on the web server
in relation to the CODEBASE for the applet, using what you know from parts 4 and
5 of this article.
Remember to account for any directory mappings that your web server does.
Again, a few examples might help. Let's say we have a Java 1.1 applet to
deploy that depends on the Powersoft classes and on the Sybase jConnect 3.0 JDBC
driver. In addition, the applet itself consists of class files that have the
package name "mycompany.sample", as in "mycompany.sample.SampleApplet". Say the
web server runs on a Windows NT machine and that the root directory of the web
server ("/" in GET requests) maps to "c:\webserver\pages".
Example 1: Deploy an applet using ONLY .class files.
<applet code="mycompany.sample.SampleApplet.class" codebase="/applets">
</applet>
|
Then the directory structure would look like:
c:\webserver
\pages
\applets
\mycompany
\sample
SampleApplet.class
etc.
\powersoft
\powerj
\ui
ResizePercentLayout.class
etc.
\db
Transaction.class
etc.
\com
\sybase
\jdbc
SybDriver.class
etc.
|
You have to manually extract the powersoft.powerj.* classes from
powerj\java\powersoft\jdk11\release\lib\powerj.zip and copy the jConnect classes
from powerj\java\jConnect\classes.
Example 2: Deploy an applet using ZIP files.
<applet code="mycompany.sample.SampleApplet.class" codebase="/applets"
archive=SampleApplet.zip,powerj.zip,jconnect.zip>
</applet>
|
The directory structure is much simpler:
c:\webserver
\pages
\applets
SampleApplet.zip
powerj.zip
jconnect.zip
|
This assumes that you put your applet files into SampleApplet.zip and you
collected the jConnect files into jconnect.zip. However, this example will
actually fail in Netscape browsers because the browsers won't download more than
one ZIP file. The next example shows how to cover all the bases.
Example 3: Deploy an applet using ZIP, CAB and .class files.
<applet code="mycompany.sample.SampleApplet.class" codebase="/applets"
archive=SampleApplet.zip,powerj.zip,jconnect.zip>
<param name="cabbase"
value="SampleApplet.cab,powerj.cab,jconnect.cab">
</applet>
|
The directory structure is the most complicated:
c:\webserver
\pages
\applets
SampleApplet.zip
SampleApplet.cab
powerj.zip
powerj.cab
jconnect.zip
jconnect.cab
\mycompany
\sample
SampleApplet.class
etc.
\powersoft
\powerj
\ui
ResizePercentLayout.class
etc.
\db
Transaction.class
etc.
\com
\sybase
\jdbc
SybDriver.class
etc.
|
The example above will support the maximum set of browsers.
7. Deploying Multiple Versions Of Classes
At some point you will upgrade your tools (for example, if a new version of
PowerJ is released) and build applets using those new tools. Chances are that
the classes you depend on may have changed, but for various reasons you only
want to use the new classes with new applets. With some care you can ensure that
all your applets coexist peacefully on the web server, even with conflicting
class versions.
All classes that are downloaded by a browser have a class loader associated
with them. The class loader is an instance of java.lang.ClassLoader and is
called by the Java interpreter whenever it needs a class loaded. Browsers use
class loaders that know how to fetch classes from a web server by sending a GET
request to the web server and then building the class from the byte stream the
server returns.
Classes loaded using different class loaders are considered to be different
classes by the Java interpreter, even if they have the same name, and even if
the same physical .class file is loaded. This is the mechanism by which a
browser can load and run multiple versions of the same class, by creating new
class loaders for individual applets or groups of applets.
A new class loader is not created for each APPLET tag. Most browsers create
new class loaders based on the CODEBASE attribute of an APPLET tag. In other
words, if two applets share the same CODEBASE they will be loaded by the same
class loader (among other things, this allows the applets to talk to each other
via static methods or static data in shared classes). Not all browsers use this
algorithm, for example the Netscape 3.x browsers create class loaders based on
the document base (the URL of the HTML page).
So to deploy multiple versions of classes keep these two rules in mind:
- Rule #1: Applets embedded on the same page must use the same versions of shared
classes.
- Rule #2: Organize your applets into separate directory trees on the web server
based on which versions of classes they use. For example, you might have one
tree for use by applets that depend on PowerJ 2.0 and jConnect 2.2, and another
for applets that depend on PowerJ 2.1 and jConnect 3.0. After setting up these
separate trees you simply set the CODEBASE attributes of each applet
appropriately. Note that on Unix web servers you can minimize the amount of disk
space used by placing files that are shared between different directory trees in
a single common area and using filesystem links to "move" them into each
tree.
A caveat: before trying to load a class from the network, the class loader
always looks at the local classpath first. Most browsers allow you to install
"trusted" classes into their local classpath you might put the powerj.zip on
every client machine, for example, to make downloads even faster. If a class is
found in the local classpath it is always used, regardless if the version on the
web server is different. In general you should avoid installing classes in the
local classpath unless you can guarantee that there will be no
conflicts.
User groups have permission to reprint this article for free
as described on the copyrights page.
|