The Applet is dead; long live the Applet!
This article provides an overview and introduction to Java Web Start, an exciting new Java application distribution technology and reference implementation of the Java Network Launching Protocol (JNLP).
I've heard it said that Sun never really intended applets to be positioned as a solution to automated application distribution, but more as a means to market the Java platform. To be fair, applets and Java technology did (even from the outset) address major portability and security issues by providing platform-independent byte-codes, byte-code verification, and sandboxing; but several critical issues remained unaddressed.
Enter JNLP, aka JSR-56, a technology that aims to provide a complete solution to the problem of Java app distribution.
Sun provides a free reference implementation of JNLP, called Web Start, which enables desktop PCs and workstations to download Java applications with little or no involvement from the end user. Of course, Web Start is just one possible implementation of JNLP. For example, a JNLP client written for a Sony Playstation is unlikely to implement JNLP in the same way as Web Start.
Web Start Features
Here's a summary of Web Start's features:
- Fully automated, Web-centric distribution and installation of Java 2 applications, applets, and extensions based on the JNLP;
- Resource caching—Application components are cached automatically on the client's machine;
- Browser independence—Applications are executed outside of the browser process and can also be launched directly from the desktop;
- JVM independence—A pre-requisite virtual machine implementation and version can be specified and, if not already present on the client machine, downloaded and installed automatically;
- Transparent updating—Versions of cached application resources are checked against those hosted on the Web server. Newer versions are downloaded and installed automatically;
- Incremental updates—Only new or modified classes and resources need be uploaded to the client's machine; and
- Incremental downloads—If required, archives can be downloaded only when first required as opposed to being downloaded immediately.
Let's make it clear that Web Start is
not applets 2.0. It has nothing directly to do with the
java.awt.applet API, although, as we shall see, the critical sandboxing features of applet technology have been retained and enhanced.
Application Life Cycle Under Web Start
Here's how an application makes it to a client's machine under Web Start:
- Using a browser, the end user clicks on a JNLP file—an XML document describing the application—which causes the file to be downloaded to the client.
- Web Start is started (by the browser) and presented with the downloaded file.
- If the JNLP file describes an application's resources that are not already present on the client's machine, these resources will be downloaded using the specified URL information in the file.
- Once downloaded, the application is started (in its own process) using program parameters obtained from the JNLP file.
The second time a JNLP file is referred to, the situation changes somewhat in Step 3: The Application Manager recognizes that the application is already present and compares the newly downloaded JNLP file with an old file. If it is established that a newer version of the application exists, the updated resource(s) will be downloaded accordingly. If not, no download takes place.
The sequence in Figure 1 shows the logical interactions involved for a newly requested application. This application comprises a single resource called wsexample.jar. Fortunately for the end user, the only thing to be done is to click once on the hyperlink that points to the JNLP file.
Figure 1. Sequence diagram for an app download using Web Start.
Installing Web Start
There is a bootstrapping procedure associated with automated application distribution, and it begins with the installation of Web Start on the client machine. Installation requires the following steps:
- Download Web Start for your chosen operating system from the JavaSoft Web site. (Version 1.0.1 includes JRE 1.3.)
- Run the installation program. The installation program adds the MIME type application/x-java-jnlp-file to the browser's MIME type database in association with the file extension jnlp. Exit the browser if prompted to do so.
To start the Application Manager under Windows, either double click on the newly installed icon on the desktop or double click on
\javaws.exe. Under Unix/Linux, go to the install directory and type
./javaws. The Application Manager window should now appear (see Figure 2).
Figure 2. Initial start-up of Web Start's Application Manager.
Configuring and Testing Web Start
That's pretty well it for the client installation, except that for those wishing to access applications hosted beyond a firewall, Web Start's proxy server settings will need to be specified. To do this:
- Start the Application Manager.
- Go to File -> Preferences.
- Depending on how you usually specify proxy settings, either click on "use browser," or click on "manual" and enter the URL (omit the prefix "http://" as it will not work) and port of the proxy server, which you can obtain from your network admin (see Figure 3).
Figure 3. Specifying Web Start's proxy settings.
When using Web Start for the first time, as well as for debugging, it is worth selecting the console and logging options to "on," together with a filename for the log file. These options can be found under File -> Preferences -> Advanced (see Figure 4).
Figure 4. Specifying console/logging options.
On the advanced tab, we can find another important feature: Clear Folder. This function is used periodically to clear cached applications from the client's system. A consequence of its usage is that apps need to be downloaded once again.
You can now verify if everything worked by trying out the demonstrations at the Web Start demo site. To run the demonstration, simply click on an app icon that downloads (via HTTP) the app's JNLP file. Web Start's Readme file provides some troubleshooting info should things not work as expected.
Once downloaded, the now cached application can be re-launched from the Application Manager (see Figure 5).
Figure 5. Launching an application from the Application Manager.
The JNLP File
The JNLP file is an XML descriptor for the application, its resources, and its security requirements. Every JNLP application needs a JNLP file (see Listing 1).
The top-level element of the JNLP file is called . The "codebase" attribute defines the base address of application resources, whereas the "href" attribute gives the location of the JNLP file itself. In general, for attributes that have URLs as values, it is possible to specify either a relative URL value (relative to "codebase," that is) or an absolute value. An absolute value will include the protocol prefix http://.
Application Descriptor Elements
The element of Listing 1 indicates that the JNLP file represents an app. The attribute "main-class" informs Web Start where the program's public static void main() method can be found, for example:
:
starlet
300
:
Program arguments can also be specified by adding the
sub-elements. These end up in the string array argument of the
main() method.
Applets Descriptor Elements
Applets can also be deployed with JNLP by providing an as opposed to an . The attributes of this element correspond to those we are used to providing in HTML using the applet tag, i.e., applet class name, document base, width, height, and parameters.
:
:
:
Extension Descriptor Elements
Then there are the so-called "extension elements"
and
. A
element describes a component extension that typically groups resources common to several apps; for example, frequently used GUI or back-end connectivity components. The primary benefit of this is that you can version and then deploy these common components independently of the applications. A component extension has no attributes or sub-elements and so can be written thus:
:
:
Finally, an
element describes a so-called installer extension, which is primarily used to install software elements that require a platform-dependent setup, such as a JRE or device driver. Like the application descriptor, the installer descriptor must also name the software's entry point by specifying a class with a
main() in it:
:
:
Installers are run only once for any given client. Extension descriptors serve to modularize the various resources of a rollout. The complete description of two non-trivial applications could therefore be structured as in Figure 6.
Figure 6. Application modularization with extensions.
Resource Elements
Using elements, we specify the jars, native libraries, pre-requisite JRE, properties packages, and extensions (component or installer) that make up the application.
The resources element has some optional attributes, two of which are os and arch. By specifying this, we can state that a resource is designed for a particular operating system and architecture only, for example:
This is obviously of particular significance to native libraries. The values presented correspond to the system properties
os.name and
os.arch, respectively.
Resources can be downloaded either immediately or on demand using the download attribute, with values "eager" or "lazy," respectively. The default here is "eager." This feature can be used to reduce start-up latency of an app.
:
:
:
:
Finally, a resources element may refer to component or installer extensions.
:
href="libs/bc-reader-win.jnlp">
:
:
The JNLP files referred to here are downloaded and processed in much the same way as the parent JNLP file. If the addressed extension is a component extension, then the extension's resources will be downloaded and will ultimately form part of the app's
CLASSPATH. If it points to an installer extension, then the installer will be downloaded and executed.
The Security Element
The element of the JNLP file describes the permissions environment in which the application needs to operate. Omitting the security element altogether gives the application similar rights an unsigned applet has when downloaded by a browser:
- All jar file resources named in the element of the JNLP file must originate from the same host; and
- No native libraries can be used, i.e., no nativelib elements can be specified in the JNLP.
In contrast to an applet, an unsigned JNLP application is permitted to exit the JVM (with
System.exit()).
For trusted applications, the current JNLP spec currently names two possible, mutually exclusive sub-elements of the security element, which look like this in the JNLP file:
:
:
or
:
:
The
element refers to the permissions environment
java.security.AllPermissions, which grants the app the same level of control over its execution environment as a regular standalone application. The
refers to a limited permissions environment that, among other things, allows socket connections to be opened to an arbitrary host and to load native libraries. For the full list of permissions for these variants, refer to the JNLP spec at JavaSoft's Web Start site.
The following conditions must, however, be satisfied before a launched Web Start application is granted these permissions:
- The application is signed; and
- The end user trusts the certificate used to sign the application. To this end, Web Start prompts the end user to accept or reject the certificate.
The Information Element
The JNLP file's
element provides meta-information about the application. This information is typically shown to an end user during downloading or following downloading in the window of the application manager (see Figure 5).
Corporate Inventory
Cutting Edge GmbH
Corporate Inventory
No!->
One can also specify for the program to run offline by using the
sub-element. In this example, however, this is not the case.
Making Your Own JNLP-Enabled Applications
Any Java program, including those that depend on native code, can potentially be deployed via JNLP. Here's what to do:
- Ensure your application can access resources (icons, properties files, etc.) from a jar file (see "Accessing Program Resources" below).
- Package your application and other resources in one or more Java aARchive (jar) files. If the application requires privileged access to client resources, it will have to be signed.
- Write a JNLP file for the application by copying and then modifying an existing JNLP file, such as the one in Listing 1.
Accessing Program Resources
One of the rules of packaging JNLP applications is that everything must be packaged in a jar file. This rule also applies to program elements such as icons and properties files, etc., which—before Web Start—one might have been tempted to obtain from the file system using a
FileInputStream.
To access these items from a jar, we must go via a class loader, as the following code excerpt demonstrates:
:
ClassLoader cl =
getClass().getClassLoader();
Icon corporateLogo = new ImageIcon(
cl.getResource("images/logo.gif") );
:
This code assumes a jar structure as follows:
:
com\mycorp\code\MainProg.class
:
images\logo.gif
:
This is a common but, thankfully, simple software modification that must be executed when making existing applications JNLP-enabled.
Setting Up a JNLP Application Host
JNLP applications need to be hosted on an HTTP server. Fortunately, this is usually quite easy:
- Set up the Web server so it associates JNLP files with the MIME type application/x-java-jnlp-file. With Tomcat, for example, make a MIME mapping entry in the file Tomcat/conf/web.xml.
- Make the application's resources (jars, etc.) and JNLP file accessible via HTTP by placing them in the Web server's document path. The URL of the application specified in the JNLP file must obviously correspond to the jar's location.
- Provide a link from some Web page to the JNLP file.
For the most basic behavior, these few steps are all that is required. Of course, with this basic setup, providing an application update implies producing a new jar and the client uploading—even if 90% of the application is unchanged. Fortunately, Web Start allows us to be much more economical with system resources than this.
Supporting Incremental Updates
Incremental updates permit a program's updated parts (its "deltas") to be shipped and installed, rather than the entire application. This can significantly increase updating speed, as well as reduce network traffic.
Incremental updates come into play when an exact or, alternatively, a minimum version number is specified for a particular resource in the JNLP file, for example:
When a JNLP client, such as Web Start, comes to request this resource from the HTTP server, it must encode the HTTP GET request according to the JNLP specification, which incorporates the version id of the requested resource.
http://www.cuttingedge.ch/wsapps/wsexample.jar?
version-id=1.1%2B¤t-version-id=1.0
In this example, we see the JNLP client has also stated the
current version id. This extra information can be used by the application host to ship a software delta. But to support this feature, the Web server needs to be equipped with a little intelligence and this is typically provided by a servlet.
Version 1.0.1 provides the JnlpDownloadServlet, which serves exactly this purpose. In fact, the JnlpDownloadServlet does a lot more than deliver software updates. First, the servlet provides a convenient mechanism for deploying application resources from a Servlets 2.2 capable servlet container (e.g., Apache's Tomcat) by allowing the software to be packaged as a Web application archive or war file. Here's an example war file structure that corresponds to the JNLP in Listing 1:
/index.html
/app/warehouse.jnlp
/app/warehouse_V1.1.jar
/app/images/logo.gif
/WEB-INF/web.xml
/WEB-INF/lib/jnlp-servlet.jar
/WEB-INF/lib/jaxp.jar
/WEB-INF/lib/parser.jar
We see that the
JnlpDownloadServlet, as well as a JAXP-capable XML parser, are included in the war file. This and other details of setting up JNLP archives are explained in the guide that accompanies the developer's kit.
The JnlpDownloadServlet also automatically generates jar files that contain the software deltas on the fly by using the jardiff utility. This tool compares the previous version's jar with the newest version and creates a file representing the difference between them. The result, called a jar-diff file, is delivered to the client instead of an entire archive, whereupon the original jar is updated.
Using the JnlpDownloadServlet, there are two ways to specify the version numbers of resource archives. The simplest variation uses a special naming convention for the name of the archive. The war file structure above simply specified a version of V1.1. However, the name can also include operating system, architecture, and locale. For example:
:
/app/wsexample_V1.1_OWindows_NT_Ax86_Len.jar
:
where
V=Version
O=Operating System
A=Architecture
L=Locale
The operating system and architecture values here correspond to the attributes
os and
arch of the JNLP file's resource element.
The second way to specify resource versions is to provide an XML document, version.xml, that contains the required version information. Details of this are provided with the developer download. Whichever way you prefer will depend on your build procedures.
Finally, you need to make sure your servlet container is correctly configured so JNLP client's URL requests are sent to the JnlpDownloadServlet. Your servlet container's documentation tells you how to do this. But be aware that not all of today's servlet containers fully support JNLP, so consult your vendor before investing too much time.
Signing Applications
Since Java 2, the standard JDK comes with two command line tools that are used to sign each resource that makes up the application: keytool and jarsigner. The keytool utility is designed to manage a database of key and certificate information called a keystore. The jarsigner tool is used to electronically sign to a jar. Both of these tools come with JDK 1.2 and higher. The JDK1.3 documentation set comes with an improved user guide.
For test purposes, a test keystore can be generated using the following keytool command: $ keytool -genkey -keystore testKeystore -alias mycerts.
The command creates the keystore after you have entered some organizational information. To create a self-signed test certificate, use a command such as: $ keytool -selfcert -alias mycerts -keystore testKeystore.
Once the test certificate has been generated, an application resource jar is signed using the command: $ jarsigner -keystore testKeyStore myComponent.jar mycerts.
Of course, an application signed with a test certificate can hardly be called authenticated. "Credible" certificates are obtained from a reputable certification authority, either internally in some organizations, otherwise externally from a company such as VeriSign.
Once a signed application is downloaded to the client, the end user is prompted to either accept or reject the certificate (see Figure 7).
Figure 7. Prompting the end user before a JNLP application is granted access to the local machine.
The JNLP API
The JNLP API provides a number of services that give controlled access to resources not normally available to unsigned J2SE applications. Here's a summary of the JNLP services provided with Web Start 1.0.1:
- BasicService—Is similar to the AppletContext provided with the applets API. For example, the showDocument() method allows you to display the page for a given URL in the browser.
- ClipboardService—Gives the application access to the system clipboard. It also makes it possible to perform cut-and-paste operations involving other (non-Java) applications on the desktop.
- DownloadService—Gives the application access to some of the functionality any JNLP client itself requires. With it, you can invoke resource downloads and check to see if resources are already cached.
- FileOpenService—Permits untrusted applications to open streams to files on the local disk.
- FileSaveService—Allows untrusted applications to save files to the local disk.
- PrintService—Allows a local printer peripheral to be exploited. The functionality from the java.awt.print package is used to create the objects, which represent the printed medium.
- PersistenceService—Provides cookie-like functionality for the application. Note that it is not a general persistence mechanism and the amount of name-value pair data expected to be stored on the client machine is small. Amusingly, the designers have chosen to dub the underlying mechanism "muffins."
From a security perspective, several of these services could potentially give an application opportunity to reek havoc on a client machine. Fortunately, Web Start's implementation of these services includes checks with the Security Manager. So in cases where an application's requested permissions environment does not grant immediate access, the end user will be prompted to accept or reject the proposed operation (see Figure 8).
Figure 8. Users decide if the app should be permitted access to a system resource.
Conclusion
Perhaps partly because applets failed to fully address many issues of application deployment, there has been a trend over the last couple of years to develop every conceivable kind of Web application using Java servlets and HTML-related technologies. (In fact, some IT managers are still suffering the effects of applet shellshock, and will, therefore, continue to push HTML as the only viable solution.)
While this may still be justified for Internet applications, where the target audience is often unknown or application usage is infrequent, there now appears to be fewer reasons to continue with this style of application in intranet environments. This is especially the case when every end user has access to a standardized corporate desktop PC, which can include Web Start as part of the standard rollout. The CPU and memory resources of these boxes are simply begging to be used.
With Web Start's imminent integration into JDK1.4, along with 1.4's other promised major improvements in the client programming area, we shouldn't be surprised to see a big revival in Swing-based client development.