Java Web Start to the rescue

Find out how Java Web Start aids client-side deployment

Java applets fuelled Java's initial growth. The ability to download code over the network and run it on a variety of desktops offering a rich user interaction proved quite compelling. However, Java's Write Once, Run Anywhere (WORA) promise soon became strained as browsers began to bloat and several incompatibilities emerged that were caused by the Java language itself. In the meantime, Java proved a disruptive technology yet again by making a mark on the server side.

Recently, Java began making a comeback on the client side with technologies such as Java Plug-in and, more recently, Java Web Start. Also, the Java 2 Platform, Enterprise Edition (J2EE) incorporates technologies such as JavaServer Pages (JSP) that support desktops and a multitude of client devices by serving up HTML, XML, and so on.

Using markup languages to generate user interfaces proves advantageous due to those languages' ubiquity and light weight. However, a markup-language-based UI is fairly limited. Java Web Start overcomes this main limitation while preserving some of a markup-language UI's main benefits, such as using a network URL as a launching point, updating client applications without intervention, and so on. Using Java Web Start, it's possible to design desktop Web clients that provide a rich user experience decoupled from a browser.

In this article, I will primarily look at Java Web Start. However, to begin I will provide some background on the motivation behind the technology, and compare and contrast different approaches for designing Web clients using various available technologies.

At the trail's root: Java applets

"An applet is a small program that is intended not to be run on its own, but rather to be embedded inside another application" -- so says the Applet Javadoc. Browsers represent the typical application in which an applet is embedded. Coupled with the rapid growth and ubiquitous availability of browsers, applets provided a nice delivery vehicle for distributing applications to thousands, even millions of desktop clients with the click of a mouse.

Although applets offer several advantages -- a rich user interaction, for example -- they are restricted by the environment in which they execute: the browser. Another issue is that applets are embedded in HTML. HTML downloads quickly because it focuses solely on presentation. Applets are much more general, and therefore slower to render. Mixing the two on the same page results in an impedance mismatch.

Applet developers must also support different versions of Java in various browsers, making it difficult to meet the WORA paradigm. Further, the slow download time can make invoking a Java applet a jarring experience for the user, a problem that does not improve with subsequent uses.

Finally, from a security viewpoint, applets are restricted by the sandbox environment, which provides a powerful defense against rogue applications. Although this model is simple to understand, it is fairly inflexible in that it does not support actions, like local disk access, that are reasonable requirements even for network-downloadable code, provided that the actions can be accomplished securely.

Many of these issues are solved via the Java Plug-in. However, even with the Java Plug-in, the user interaction remains constrained by the application hosting the applet.

Java conquers the server turf

Java morphed from an applet-based language, as descried above, into the programming platform of choice on the server. The language's focus shifted heavily from the client to the server side. Using server-based technologies, it was easier from a program maintenance viewpoint to control from the server the user interface for the client. The user interface centers around markup technologies like HTML, XML, XHTML, and so on. Servlets and JSPs are Java-based technologies on the server side that can be used to serve up markup languages. Servlets and JSPs are an important part of J2EE, providing an entry point to the Web clients for other Java- and J2EE-related technologies on the server.

The server-centric approach offers a responsive user interface, albeit with interactivity limited by the markup language used for the client. An advantage of this approach: support for multiple kinds of clients, especially thin clients. Although the interactivity of many of these thin clients is inherently constrained by the nature of the device, thin clients typically can support one or more markup language.

Java comes back on the client

We looked at applets and then at Servlet/JSP-based technologies as the basis for Web client design. These technologies are primarily constrained by the environment in which they are hosted -- a browser or some similar technology. Although this may not prove to be a serious limitation to some applications, it is likely to limit many. A browser-based email client serves as a good example. Although browser-based email clients are quite popular, traditional email clients are more prevalent, especially in the workplace, where there is a need to sift through lots of email, apply filters, and be able to work offline in certain scenarios.

Java Web Start overcomes these user interface and connectivity limitations, and offers client-side software distribution features as well. The availability of Java Web Start on a number of different platforms makes it a powerful choice for designing desktop clients. For instance, you can use Java Web Start to add more interactive clients for J2EE applications.

Some of the ease-of-use and ease-of-programming features associated with Java Web Start include:

  • Portability: Java Web Start is available on Windows, Solaris, and Linux, and is expected to be ported to other platforms.
  • Caching: Applications launched with Java Web Start are cached locally. Thus, an already-downloaded application is launched on par with a traditionally installed application.
  • Maintainability: If the remote application is updated, Java Web Start updates the locally cached version at the application's next invocation.
  • Easy launching: Java Web Start allows applications to be launched independently of a Web browser. The application can also be launched through desktop shortcuts, making launching the Web-deployed application similar to launching a native application.
  • Ability to work offline: An application can be used in situations where launching through the browser is inconvenient or impossible.

The table below compares the different technologies used for designing Web clients. These different factors influence the design of these Web clients.

Web-client factor comparison
FactorsAppletsXML/HTML-based clientsJava Web Start
User interface Moderate to sophisticated Simple to moderate Moderate to sophisticated 
Offline support? No No Yes 
UI response Network independent Network dependent Network independent 
Interactivity Browser limited Browser/markup limited Open 
First use response Minutes Seconds Minutes 
Subsequent use response Minutes Seconds Seconds 
Bandwidth usage Variable Fixed Flexible 
Lightweight client support Limited Open Limited 

As you can see, while applets take roughly the same time to download on first use and each subsequent use, Java Web Start applications will load faster on subsequent uses due to the product's inherent caching features.

Another point to note: no single approach will cover all situations. Later, I'll show how you can employ a combined approach.

Java Network Launching Protocol and API

We explored Java Web Start briefly. Next, we'll look at the Java Network Launching Protocol (JNLP) specification, which is the basis for Java Web Start. JNLP provides a Web-centric protocol for provisioning (i.e., deployment and other issues associated with it) and running Java 2-based applications. The specification includes:

  • A Web-centric application model with no installation phase, providing transparent and incremental updates.
  • The syntax and semantics of a .JNLP file, which packages applications on a Web server and delivers and runs them on clients.
  • A standard execution environment for an application, which is similar to the sandbox model but enhanced with additional APIs for local clipboard and disk access. Using standard code-signing techniques, it is possible to provide an unrestricted environment as well.

In essence, JNLP provides a way for an application to run from a codebase accessible over the Net. It provides an environment similar to what would happen if URLs were supported in the classpath, a hypothetical example of which would be:

java -classpath http://www.mysite.com/app/MyApp.jar com.mysite.app.Main

In addition, JNLP provides support for multiple versions of Java, support for native libraries, and a number of ease-of-use features. Java Web Start is a product based around the JNLP specification. Other products using the specification are also available (see Resources).

Having demonstrated the distinction between the JNLP specification and the products based on it, I will now turn primarily to Java Web Start. I will show each of its features, starting with making a simple application network accessible and deployable, then moving on to code signing, and finally to using some of the JNLP API. In the process, we will look at the .JNLP file, which describes an application as an XML document.

Java Web Start -- getting started

Now that you've briefly seen the JNLP specification, let's take a look at one product based on it: Java Web Start. To use Java Web Start's full feature set, some minimal installation and configuration is required on both the server and the client. We will look at each step using some simple examples, as outlined below.

Server-side setup

I'll show you how you can make the example program -- SimpleExample, a simple (Java Foundation Classes) JFC demonstration -- network accessible using JNLP. This example is provided as part of the Java SDK. As outlined in the developer's guide (see Resources), create the SimpleExample.jnlp file:

<?xml version="1.0" encoding="utf-8"?> 
<!-- JNLP File for SimpleExample Application --> 
  <jnlp
  codebase="http://anvil:8001/" 
  href="SimpleExample.jnlp"> 
    <information> 
       <title>Swing Application - Hello World</title> 
       <vendor>Rags</vendor> 
       <description>Swing Application - Hello World</description> 
       <description kind="short">Swing Application - Hello World</description> 
       <offline-allowed/> 
     </information> 
     <resources> 
       <j2se version="1.3"/> 
       <jar href="SimpleExample.jar"/> 
     </resources> 
     <application-desc main-class="SimpleExample"/> 
</jnlp>

The XML document above is self describing. Details about the application, including how it can be accessed by the Web server, are provided by the codebase property; more detailed information is enclosed between the <information> and </information> tags. The version tag illustrates which version of the Java 2 Platform, Standard Edition Runtime Environment should be used. It is possible to provide a prioritized list and specific values for the JRE versions. For more information on the syntax and semantics of the file, refer to the Resources section below.

Having created the .JNLP file, create the SimpleExample.html file used to launch the application:

<html>
  <head>
      <title>SimpleExample demo!</title>
  </head>
  <body>
       <a href="SimpleExample.jnlp">Launch SimpleExample Application</a>
  </body>
</html>

The developer's guide outlines how to develop the HTML file to detect whether or not Java Web Start is installed, and how to install it if necessary.

Package the application into the file SimpleExample.jar:

D:\jdk1.2\demo\jfc\SIMPLE>jar -cvf SimpleExample.jar *.class
added manifest
adding: SimpleExample.class (in=402) (out=283) (deflated 29%)
adding: SimpleExample$RadioListener.class (in=1444) (out=829) (deflated 42%)
adding: SimpleExample.class (in=3046) (out=1581) (deflated 48%)

Finally, configure the Web server to use the appropriate MIME type. The server must return the application/x-java-jnlp-file MIME type for JNLP files in order for Java Web Start to invoke. This is obviously Web-server-dependent. In Jigsaw, the jigadmin tool can achieve this. Tucked away in http-server/Indexers/default are extensions to which <JNLP> needs to be added to return the MIME type as noted above.

Client-side setup and deployment

Install Java Web Start version 1.0 or 1.0.1 on the client.

On the client side, launch a browser and point it to the HTML file on the server. If Java Web Start is correctly installed, the Web server configured for the .JNLP extension, and the application appropriately provisioned as indicated above, a splash screen should appear, followed by a window indicating that the application is being downloaded, as shown in Figure 1.

Figure 1. Start window indicating application download. Click on thumbnail to view full-size image. (25 KB)
Figure 2. Hello World application launched using Java Web Start. Click on thumbnail to view full-size image. (8 KB)
Figure 3. Window enabling creation of a desktop shortcut. Click on thumbnail to view full-size image. (24 KB)

Finally, the networked application is launched locally, as shown in Figure 2.

This simple example application illustrates some of JFC's features. It's worth noting that the networked application was launched by a single click and was decoupled from the browser (which would have restricted the user interaction).

Depending on the options set up for Java Web Start, launching the same networked application will create a desktop shortcut at the discretion of the user. Figure 3 shows the dialog box where the user can make that choice. Creation of the desktop shortcut happens only on Windows platforms.

This simple Hello World application was intended to drive home the concepts of Java Web Start. The Java Web Start installation provides demonstrations of applications that have a more advanced user interface; such applications are appropriately decoupled from the browser.

This application, however, does not perform any operations restricted by the sandbox. To illustrate more of Java Web Start's advantages, I'll next demonstrate an application that performs local disk access.

Java Web Start security

We just looked at a simple example; now, we will look at another simple example that performs some operations not permitted in the default sandbox environment. Trusted signed code can, however, leave the sandbox, as we'll see. As a basis, we will use some of the code I used in my earlier Java security articles. I've modified the Java program to exit when the window closes if invoked either as an application or using Java Web Start.

Here's the code, with modifications:

/**
  * By default, this raises a security exception as an applet.
  *
  * With JDK 1.2 appletviewer, 
  *  if you configure your system to grant applets signed by "Duke"
  *  and downloaded from the Java Software Website to write a file
  *  to your /tmp directory (or to the file named "C:\tmpfoo" on a 
  *  Windows system), then this applet can run.
  *  
  * @version JDK 1.2
  * @author  Marianne Mueller
  * @Modified by Raghavan Srinivas[Rags]
  */
import java.awt.*;
 import java.awt.event.*; 
import java.io.*;
import java.lang.*;
import java.applet.*;
public class writeFile extends Applet {
    String myFile = "/tmp/foo";
    File f = new File(myFile);
    DataOutputStream dos;
  public void init() {
    
    String osname = System.getProperty("os.name");
    if (osname.indexOf("Windows") != -1) {
      myFile="C:" + File.separator + "tmpfoo";
    }
  }
  public void paint(Graphics g) {
        try {
          dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(myFile),128));
          dos.writeBytes("Cats can hypnotize you when you least expect it\n");
          dos.flush();
          dos.close();
          g.drawString("Successfully wrote to the file named " + myFile + " -- go take a look at it!", 10, 10);
        }
        catch (SecurityException e) {
          g.drawString("writeFile: caught security exception", 10, 10);
        }
        catch (IOException ioe) {
                g.drawString("writeFile: caught i/o exception", 10, 10);
        }
   }
    public static void main(String args[]) {
        Frame f = new Frame("writeFile");
        writeFile       writefile = new writeFile();
        writefile.init();
        writefile.start();
       f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}    });
        f.add("Center", writefile);
        f.setSize(300, 100);
        f.show();
    }
}

Copy the writeFile.class and writeFile.class (the class generated as a result of the anonymous inner class corresponding to the WindowAdapter) into a subdirectory and generate the signed jar file:

D:\rags\sign>signtool -d . -Z writeFile.jar -k "Raghavan N. Srinivas's Thawte Consulting cc ID" writeFile using certificate directory: .
Generating writeFile/META-INF/manifest.mf file..
--> writeFile.class
adding writeFile/writeFile.class to writeFile.jar...(deflated 44%)
--> writeFile.class
adding writeFile/writeFile.class to writeFile.jar...(deflated 28%)
Generating zigbert.sf file..
Enter Password or Pin for "Communicator Certificate DB":
adding writeFile/META-INF/manifest.mf to writeFile.jar...(deflated 30%)
adding writeFile/META-INF/zigbert.sf to writeFile.jar...(deflated 37%)
adding writeFile/META-INF/zigbert.rsa to writeFile.jar...(deflated 28%)
tree "writeFile" signed successfully

The .JNLP file used with this application illustrates how it's possible for signed code to execute outside the default sandbox environment provided by Java Web Start. The appropriate code is illustrated in boldface:

<?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for WriteFile Application -->
<jnlp spec="1.0+"
  codebase="http://anvil:8001/"
  href="writeFile.jnlp">
    <information>
      <title>writeFile Demo Application</title>
      <vendor>Rags</vendor>
      <homepage href="docs/help.html"/>
      <description>writeFile Demo Application</description>
      <description kind="short">A demo of writeFile app. </description>
      <icon href="images/swingset2.jpg"/>
      <offline-allowed/>
    </information>
   <security> 
      <all-permissions/> 
    </security> 
    <resources>
      <j2se version="1.3"/>
      <jar href="writeFile.jar"/>
    </resources>
      <application-desc main-class="writeFile"/>
</jnlp>

Provide an HTML file to launch the application as well. Now the application is ready to run. If the code has been signed and provisioned correctly on the server, the window shown in Figure 4 should pop up. The window will give the user the choice of continuing to run the application or to terminate it.

Figure 4. Dialog popup for running signed applications. Click on thumbnail to view full-size image. (35 KB)

Clicking on the Start button will cache the signer locally, and the dialog popup will not appear for subsequent invocations of the same application. If you don't want to trust the signer subsequently, the local cache can be cleared using the Java Web Start Application Manager, as you will see later.

So far, you have seen how Java Web Start can be used without any programming. The JNLP and Java Web Start API provide a set of classes for user friendly of client-side applications. For example, even though code is unsigned, it may still be used for local disk access with the user's consent. This is somewhat akin to the Save As option and manipulating cookies available in most browsers.

The Java Web Start APIs deal with this limited set of out-of-the-sandbox operations in a controlled manner, by limiting interaction to the system explicitly via dialog boxes.

Use the JNLP API

We just saw how an application can access a local filesystem by signing the code. This can be accomplished by using the API as well.

I will discuss only some API details and use some of those to modify the writeFile example we discussed earlier. These APIs come with the developers' pack, which needs to be installed as a Java extension to successfully compile the code and subsequently generate the .jar files. Rather than installing the extensions, you could also include jnlp.jar in the classpath. Refer to the Resources section below for a more detailed explanation of the API. Examples of the API are:

  • ClipBoardService: Includes methods for accessing the shared system-wide clipboard
  • FileContents: Encapsulates the name and contents of a file
  • FileOpenService: Allows the user to choose a file from the local filesystem
  • FileSaveService: Allows the user to save a file to the local filesystem
  • JNLPRandomAccessFile: Includes methods for both reading and writing to a random access file
  • PersistenceService: Includes methods for storing data locally on the client system
  • PrintService: Includes methods to access printing functions

Many of these APIs apply even when run in an untrusted environment. That is, the code does not have to be signed and trusted by the user for the operation's successful completion. In some cases, Java Web Start will warn the user of the potential security risk of letting an untrusted application access potentially confidential information.

Let's dissect some of these APIs further. The FileOpenService, for instance, supports methods like openFileDialog() and openMultiFileDaialog(), which select a single file or multiple files, respectively. They return FileContents and FileContents[], respectively. Likewise, FileSaveService supports methods like SaveAsFileDialog and SaveFileDialog. As you might expect, these APIs interact with the user via dialog boxes explicitly.

In the example below, we will look at the earlier application that was converted to write to a file picked by the user, rather than to /tmp/foo. The application uses some of the APIs mentioned above. This application need not be signed:

/**
  * This program uses JNLP API to write to a file
  * that is selected by the user
  *  
  * @author  Rags Srinivas
  */
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.*;
import java.applet.*;
import javax.jnlp.*;
public class writeFile extends Applet {
    static FileOpenService fos;
    static JNLPRandomAccessFile raf;
    static FileContents fc;
    static int count=0;
    public void init() {
    
        // Look up a FileOpenService
        try { 
            fos = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService"); 
        } catch (UnavailableServiceException e) { 
            fos = null;
        } 
        if (fos != null) { 
            try {                
                // get a file with FileOpenService
                fc = fos.openFileDialog(null, null);
                // If valid file contents
                if (fc != null) {
                    long grantedLength = fc.getLength(); 
                    if (grantedLength + 1024 > fc.getMaxLength()) { 
                        // attempt to increase the maximum file size defined by 
                        // the client 
                        grantedLength = fc.setMaxLength(grantedLength + 1024); 
                    }
                    // Open the file for read write
                    raf = fc.getRandomAccessFile("rw");
                } 
             } catch (Exception e) { 
                 e.printStackTrace(); 
             } 
         } 
    }
    public void paint(Graphics g) {
        String msg="JWS can stun you! ";
        if (fos != null && fc != null) {
            try {
                // seek to the beginning and write 
                raf.seek(0); 
                raf.writeBytes(msg + count++);
            } catch (Exception e) { 
                e.printStackTrace(); 
            }
        } 
    }
    public void destroy() {
        if (fos != null && fc != null) {
            try {
                // close the file
                raf.close(); 
            } catch (Exception e) { 
                e.printStackTrace(); 
            }                   
        }
    }    
    public static void main(String args[]) {
        Frame f = new Frame("writeFile");
        final writeFile writefile = new writeFile();
        writefile.init();
        writefile.start();
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) { writefile.destroy(); System.exit(0);}    });
        f.add("Center", writefile);
        f.setSize(300, 100);
        f.show();
    }
}

In the init() method, the file the user picks is opened as a random file for both read and write. The paint() method writes a fixed message appended with an incrementing count. Finally, the destroy() method closes the file. Invoking this application will bring up a dialog box through which the user can interact to select a local file to write to.

Note that the user explicitly picks the output file; no other file can be accidentally or maliciously overwritten. This means that the application securely modifies the local filesystem.

Although the code is written to work both as an applet and an application, this functionality will not be available in the applet environment since the JNLP APIs will not be available there.

The final piece in Java Web Start I will demonstrate is the application manager.

Java Web Start Application Manager

You can employ the Java Web Start Application Manager for a variety of administrative and related tasks. You can set the http proxy, view and start applications, create desktop shortcuts, and set other advanced preferences. The main window is illustrated in Figure 5.

Figure 5.Java Web Start Application Manager. Click on thumbnail to view full-size image. (35 KB)
Figure 6. Java Web Start Application Manager preferences. Click on thumbnail to view full-size image. (40 KB)
Figure 7. Java console. Click on thumbnail to view full-size image. (18 KB)

You can manipulate other preferences as well, as illustrated in Figure 6. Examples include clearing the local cache, setting options on desktop shortcuts, and so on.

Debug Java Web Start applications

Using the application manager, it is possible to log the output or display the Java console by appropriate options in Preferences/Advanced. The Java console window is shown in Figure 7.

Combine servlets/JSPs, applets, and Java Web Start

Having shown Java Web Start's benefits I'll now turn to applets running in a plug-in environment and clients employing servlet/JSP-supported markup languages.

Consider an application that can be browsed by a variety of clients but is typically set up and administered on a desktop. In such a situation, it's possible to use servlets/JSP to support browsing, while the setup or administration functions are done using Java Web Start to provide a rich user interface.

You can employ applets in situations where sophisticated users need fine-grained security or situations where the browser is the de facto client.

None of these technologies are mutually exclusive. It is fairly easy to mix and match in the best interest of the application requirements.

Conclusion

We started where the Java revolution began -- Java applets. Middle-tier technologies, like servlets and JSPs, enabled client-side presentation and solved some issues with applets. However, with servlets and JSPs, the user interaction was confined to the hosted environment. Java Web Start technology overcomes this limitation while still retaining most of the advantages of the other technologies used hitherto to design Web clients.

We looked at several examples illustrating Java Web Start's different features. Java Web Start and JNLP offer a powerful paradigm to design Web clients by providing a rich user interaction without confining functionality to a browser. Some combined approaches were mentioned as well, which might be applicable to certain categories of applications.

Raghavan Srinivas is a Java technology evangelist at Sun Microsystems who specializes in Java and distributed systems. He is a proponent of Java technology and teaches graduate and undergraduate classes in the evening. Srinivas holds a master's degree in computer science from the Center of Advanced Computer Studies at the University of Southwestern Louisiana. He enjoys hiking, running, and traveling, but most of all loves to eat, especially spicy food.

Learn more about this topic

  • For over 100 insightful Java tips from some of the best minds in the business, visit JavaWorld's Java Tips index
    http://www.javaworld.com/javatips/jw-javatips.index.html
  • Sign up for the JavaWorld This Week free weekly email newsletter to learn what's new at JavaWorld: http://idg.net/jw-subscribe

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