Using Java applets and applications portably

Part 1: Applets that are also applications

One problem with Java applets is that the HTML markup needed to render them correctly, is not standard across browsers. Oracle recommends the use of JNLP combined with a bit of Javascript magic (deployJava.js) to standardize both applet and application deployment. This solution however, has some problems:

  • deployJava.js could take readers off the page: This happens if the deployJava.js script detects that there is no Java Runtime installed on the reader's machine. It immediately whisks them directly to Oracle's website prompting them to install Java. The original page containing the applet is not displayed before this happens. This behavior is confusing and unfriendly to the reader. The reader is not expecting to be taken off the site. They should be given the opportunity to get some context by reading the page and deciding for themselves if it makes sense to install Java on their systems. (See the next article in this series for a solution.)

  • Inconsistent launch mechanisms: While applets are started automatically, applications require a custom launch button whose look and feel doesn't necessarily fit with the design of the page. deployJava.js provides for a way to customize the button image,but what is really needed is a clean CSS implementation.

  • Annoying differences between UI code for applets and applications: Differences in the APIs for initializing applets and applications necessitate changes in application code to make it run as an applet. (Read about the solution.)

Deploying Applets

It should be possible to deploy an applet or application as shown below.

Demo Applet & Application

Click button to start applet
 
 

Source Code

Download tar.gz, zip

Documentation

 

Note that neither the applet nor the application starts automatically when the page loads. They only start when the launch buttons are pressed. The buttons will prompt the user to install Java if it is not already installed, before starting the applet or application. In addition, the launch buttons are just CSS and can be customize to fit the look and feel of the page. Finally, the user has a choice of launching either the applet or the application. Depending on the situation one or the other launch method will make more sense.

The rest of this article describes how to do this with a combination of Java, Javscript and CSS. (Polyglot programming indeed!)

A Combined Applet and Application

Java applets differ from Java applications in how their UI is created. For a Java applet, the GUI container (a sub-class of java.awt.Container,) has already been created by the applet framework (javax.swing.JApplet) at the point user code is invoked in the applet's init method. For an application, the GUI container needs to be created (Typically a javax.swing.JFrame containing the actual content pane. The code shown below, extends javax.swing.JApplet to create a class that abstracts away the differences between applets and applications.

public abstract class AppletApplication
  extends JApplet implements Runnable {
  
  private Container container = null;  

  public void startGUI() {
    try {
      SwingUtilities.invokeAndWait(this);
    } catch (Exception ex) {
      System.err.println(
        "Caught exception while trying to execute " 
        + "AppletApplication.run(): " 
        + ex.toString());
    }
  }
  
  protected abstract String getWindowTitle();
  protected abstract void createGUI(Container container);

  @Override
  public void run() {
    // Step 1: Ensure the container is set.
    // The container is normally set by the init() method
    // of the applet. If the program is not being run as
    // an applet, then the init() method is not called and
    // container is not set in that case we're running as
    // an application and should set the container as an
    // application would.
    JFrame frame = null;
    if (container == null) {
      frame = new JFrame(getWindowTitle());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      container = frame.getContentPane();
    }

    // Step 2: Create the GUI
    createGUI(container);

    // Step 3: Display the frame if it's not null.
    // The frame is not null only if it was created 
    // in step 1.
    if (frame != null) {
      frame.pack();
      frame.setVisible(true);
    }
  }

  @Override
  public void init() {
    container = this;
    startGUI();
  }
}

The UI code for both types of invocation, can simply be placed in the createGUI(Container container) method of a sub-class. This is most easily done with a sub-class of AppletApplication that implements this method, as shown below.

  AppletApplication app = new AppletApplication() {
      
    @Override
    protected String getWindowTitle() {
     return 
       "AppletApplication "
       + "-- An applet that is also an application";
    }
      
    @Override
    protected void createGUI(Container container) {
      JLabel label = new JLabel("Applet cum Application");
      container.add(label);		    	  
    }
  };

An application can be invoked as follows from within a main function.

  public static void main(String[] args) {
    JNLPAppletApplication app = new JNLPAppletApplication();
    app.startGUI();
  }

The code above abstracts away the differences between applets and applications. The source code for the demo applet can be downloaded as a tar.gz or, as a zip archive.

The next article in this series describes the Javascript framwork that allows a user to control the launch of Java applets on a page.