Java Programming

Applets & Web Start Applications

Applets

An applet is a Java program, which can be downloaded from a remote server and executes inside the web browser of the local machine. Most web browsers (such as Firefox, Chrome, Internet Explorer) have a built-in (or plug-in) Java Runtime (JRE) for executing Java applets (just like most web browsers have plug-ins for running flash, JavaScript, VBScript, and other programs).

First Applet

Let's begin with an applet that says "Hello, world!" inside the browser.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
/**
 *  First Java Applet to say "Hello, world" on a web browser
 */
public class HelloApplet extends Applet {   // to save as "HelloApplet.java"
   public void paint(Graphics g) {
      setBackground(Color.CYAN);    // background color
      g.setColor(Color.BLACK);     // drawing color
      g.setFont(new Font("Times New Roman", Font.BOLD, 30));  // set font face, bold, size
      g.drawString("Hello, world", 20, 80);              // start at baseline (20,80)
   }
}

Compile the applet using the JDK compiler "javac.exe":

> javac HelloApplet.java

You CANNOT run the applet using JDK runtime "java.exe". Applet is a graphic program that runs inside a web browser, using the web browser's built-in (or plug-in) JRE. Applet is embedded in an HTML page (in much the same way as images, audios, and videos are embedded in an HTML page).

To run an applet, you need to create a HTML file, which embeds the applet. Use a programming text editor to enter the following HTML codes and saved as "HelloApplet.html" (or any filename of your choice). Note that HTML, unlike Java, is not case sensitive, and places no restriction on the filename.

1
2
3
4
5
6
7
8
9
10
<html>
<head>
  <title>Hello-World Applet</title>
</head>
<body>
  <p>My first Java applet says:</p>
  <applet code="HelloApplet.class" width="400" height="150">
  </applet>
</body>
</html>

You can run the applet by loading the HTML file created into a web browser. Double-click the “HelloApplet.html” in Windows Explorer (or from the browser, select "file" menu ⇒ "open" ⇒ "browse" and select "HelloApplet.html").

JDK provides a utility called "appletviewer.exe" for testing applet, in the early days of Java. Since web browser is everywhere nowadays, you should use a web browser to see the actual effect instead. You should try on all the common browsers (such as IE, firefox) if you want to put your applet in production. Appletviewer processes only the <applet> tag, and ignores all other tags in a HTML file. To use appletviewer, issue command:

> appletviewer HelloApplet.html

Dissecting the "HelloApplet.java"

Dissecting the "HelloApplet.html"

More Applets (in JDK's Demo)

Try the "demo" applet provided by the JDK (kept in directory "$JAVA_HOME\demo\applets"). For examples, "Clock", "MoleculeViewer", "SortDemo", and "TicTacToe". You may study the applets' source files and the associated html files.

HTML's <Applet> Tag

HTML provides an <applet>...</applet> container tag for embedding Java applet, with the following attributes:

<applet> tag is deprecated in HTML 4.0 in place of a more general <object> tag. However, it is still commonly-used today and is widely supported by the web browsers.

You can use <param> tag to pass parameters (or arguments) into applet.

Jaring Up Classes

As mentioned, if your applet involves more than one classes, it is more efficient to jar them up into a single file for distribution, as jar compresses the file size (just like zip).

For example, suppose that our applet has two classes: a main class called HelloAppletAgain.java and a helper class called HelloAppletHelper.java.

// Main class
import java.applet.Applet;
import java.awt.*;
public class HelloAppletAgain extends Applet {
   public void paint (Graphics g) {
      setBackground(Color.GREEN); // background color
      g.setColor(Color.BLUE);     // drawing color
      g.drawString((new HelloAppletHelper()).getMessage(), 5, 30);
   }
}
// Helper class to return a greeting message
public class HelloAppletHelper {
	public String getMessage() {
	   return "Hello, world again!";
	}
}

You can jar the classes together using the JDK utility "jar.exe" from cmd shell:

> jar -cvf HelloAppletAgain.jar HelloAppletAgain.class HelloAppletHelper.class

The following HTML script starts the applet:

<html>
  <head><title>First Java Applet</title></head>
<body>
  <h2>My first Java Applet says:</h2>
  <applet 
     code="HelloAppletAgain.class"
     archive="HelloAppletAgain.jar"
     width="400" height="100"></applet>
</body>
</html>

More On Applets

Applets are mobile programs. In the old days, we used to correct the data in magnetic tape (or punch cards) and bring the data to the computer for processing. With mobile program, you can send the program (which is much smaller) down to the data site and processed the data locally. This is possible as Java program are portable and run on all platforms.

With the availability of mobile programs such as applets, why buy word processor, spreadsheet or some expensive software? Just download an applet, use it and discard after use!

There are two problems. Firstly, applets take times to download over the network and also take times to startup (this is not really a problem today). Secondly and more importantly, applets are alien programs that run on your local machine. What stops someone from writing an applet that compromises your system - or worse, damages your machine? Nobody today will run an alien program in the local machine with all kinds of computer viruses running around.

There is strict security in place in the built-in JVM for running applets to prevent the applets from compromising your system.

In JDK 1.0, applets are considered as "non-trusted" codes and run inside a so-called sand box with no access to local file system and network resources. Applets cannot do nasty outside the sandbox. These includes:

The "sandbox" model places too much restriction on what applets can do, which resulted in a classical catch-22 situation: Applets are powerful Java programs that can perform powerful tasks. They are so powerful that may damage your local machine. Security is therefore put in place so that they cannot do damages. This limits the power and usefulness of applets and renders applets useless. Applets are not commonly used today.

JDK 1.1 introduced the notion of "trusted" codes. You can package an applet using JAR file, and sign the JAR file with your digital signature (much like signing a document or a cheque using a pen). The digital signature authenticates the source of the applets. The recipients of the applet will be presented with the digital certificate of the signer. They can then decide whether to trust the signer and run the applet or reject the applet. If a recipient accepts the applet, applet has full access to the local file system and network resource, just like any local Java application.

From JDK 1.2 onwards, JVM employs a security manager, which manages the system security based on a customizable security policy file. You can grant an applet specific permissions (such as reading local file) and deny other permissions (such as writing local file) by tailoring the security policy file. In other words, you have control of the kinds of accesses to be granted from JDK 1.2. This is in contrast of "no-access sandbox" in JDK 1.0 and "full-access" for trusted-applet in JDK 1.1.

Applets can be used to create dynamic and interactive web contents. Applets made Java popular in the early days. However, their usage is limited in the Internet environment. The security restrictions imposed on applets severely limit their functionality. JavaScript and Flash are more popular today for creating dynamic web contents on the client side nowadays. The power of Java has shifted to the server-side programming especially in the enterprise JavaEE environment and for the embedded wireless devices in the JavaME. Applets could still be useful in an Intranet environment, where network bandwidth and granting for access permission is not a concern.

JDK 1.4 introduced a deployment technology called Java Web Start to simplify the deployment of Java applications over the network. With Java Web Start, you can deploy a full-feature Java application (unlike applets, which run inside a browser) over the network. The downloaded application will be "cached" inside your local machine for subsequent re-uses. Upon subsequent activation, the Java Web Start checks if there is an update to the cached application. It downloads the newer version if there is one; otherwise, it launches the cached copy. With Java Web Start, the role of applet is even limited. However, after all these years, Web Start does not seen to be popular?!

Applets with User Interface (UI)

AWT Applet

I assume that you are familiar with UI programming (otherwise, read the earlier chapters).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
   
public class AWTAppletCounter extends Applet implements ActionListener {
   private TextField tfCount;
   private int countValue = 0;
   
   public void init() {
      setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
      add(new Label("Counter"));
      tfCount = new TextField(10);
      tfCount.setEditable(false);
      tfCount.setText(countValue + "");
      add(tfCount);
      Button btnCount = new Button("Count");
      add(btnCount);
      btnCount.addActionListener(this);
      setBackground(Color.CYAN);
   }
   
   // Event handler: increase the count and show it in the text field
   public void actionPerformed(ActionEvent e) {
      countValue++;
      tfCount.setText(countValue + "");
   }
}
1
2
3
4
5
6
7
8
9
10
<html>
<head>
  <title>An AWT Applet</title>
</head>
<body>
  <p>An AWT applet of counter:</p>
  <applet code="AWTAppletCounter.class" width="250" height="100">
  </applet>
</body>
</html>

Swing Applet

To convert an AWT applet to a Swing applet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
   
public class SwingAppletCounter extends JApplet implements ActionListener {
   private JTextField tfCount;
   private int countValue = 0;
   
   public void init () {
      Container cp = getContentPane();  // from "this" JApplet
      cp.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
      cp.add(new JLabel("Counter"));
      tfCount = new JTextField(10);
      tfCount.setEditable(false);
      tfCount.setText(countValue + "");
      cp.add(tfCount);
      JButton btnCount = new JButton("Count");
      cp.add(btnCount);
      btnCount.addActionListener(this);
   }
   
   // Event handler: increase the count and show it in the text field
   public void actionPerformed(ActionEvent e) {
      countValue++;
      tfCount.setText(countValue + "");
   }
}
1
2
3
4
5
6
7
8
9
10
<html>
<head>
  <title>A Swing Applet</title>
</head>
<body>
  <p>A Swing applet of counter:</p>
  <applet code="SwingAppletCounter.class" width="300" height="100">
  </applet>
</body>
</html>

Passing Parameters into Applet

[TODO] Outdated, need to check

<html>
<head><title>A Swing Applet</title></head>
<body>
<!-- for IE only,  use EMBED tag for Netscape -->
<object classid="clsid:8ad9c840-044e-11d1-b3e9-00805f499d93" width="250" height="80" align="left">
  <param name="code" value="SwingApplet.class">
  <param name="type" value="application/x-java-applet;version=1.4">
  No JDK 1.4 support for Applet!
</object>
   
<!-- for Netscape  only, use OBJECT tag for IE -->
<embed type="application/x-java-applet;version=1.4" code="SwingApplet.class" width="250" height="80" align="left">
  <noembed>No JDK 1.4 support for Applet!</noembed>
</embed>
</body>
</html>

Jaring up the classes in an Applet

See below under Web Start Application.

Applet's Life Cycle & Methods

Java Web Start Applications (JDK 1.4)

Java Web Start was introduced in JDK 1.4 to simplify the deployment of full-feature Java applications over the web.

Traditional desktop applications are usually platform dependent and cannot be deployed over the web. Java Applets (since JDK 1.0) provide a mean to deliver and distribute Java applications over the network. However, applets take considerable times to download, load, and execute. Applets are not full-feature GUI application, as it extends from java.applet.Applet or javax.swing.JApplet (instead of javax.swing.JFrame). If you re-run an applet, you have to download the applet all over again, even if there is no change in code.

Java Web Start, works like Java applets, allow you to deliver and distribute Java applications to your clients over the network. Unlike applets, almost any full-feature Java application that runs on desktop can be delivered. The downloaded Java applications will be "cached" inside the local machine for subsequent re-uses. In the subsequent launch, the Java Web Start checks if there is an update to the cached version. It downloads the new version if there exists; otherwise, the cached copy will be launched.

The process can be summarized as follows:

  1. A user launches a Web Start application, either via a web browser, desktop or other means.
  2. Web Start runtime queries the web to determine whether the resources needed for the requested application are already downloaded and cached. If the most recent version of the application is cached, the application will be launched from the local cache immediately.
  3. If the resources are not present or an upgrade is available, Web Start runtime will download the needed resources and then launch the application. The downloaded resources will be cached for subsequent re-uses.
  4. An "offline" mode is available, which tries to query the web for any upgrade but time-out in a few seconds. If a new version is detected before the timeout, it will be downloaded, cached and launched. Otherwise, the previously cached copy will be launched.

Web Start Security

Security is the paramount concern for deploying applications over the web. As the deployed application runs inside the client's machine, it could maliciously or accidentally damage the client's machine if no proper security measures are taken. As a general rule, nobody should run an alien program with unrestricted access to the local disks and network, if the source of the program cannot be satisfactorily authenticated.

Security strategy for Java Web Start application is similar to Java applets. Java Web Start applications can either:

  1. Run inside a "sandbox", which is a protective environment with no access to local disks and network resources (other than connecting to the host where the application resides). The security mode is meant for applications from a non-trusted source.
  2. Run with granted permissions, for signed applications from a trusted source. The application provider must digitally sign the jar file. The client will be prompted to accept the digital certificate of the provider before the application is launched.

Java Network Launching Protocol (JNLP)

Java Web Start is a Reference Implementation (RI) of the Java Network Launching Protocol (JNLP) technology.

Java Web Start is designed as a "helper application" to a web browser. A helper application is an add-on to a web browser, which will be activated if the browser receives a certain pre-configured MIME type. When a user selects a link that is associated with a web start launch file (i.e., JNLP file with a MIME type of "application/x-java-jnlp-file" and file extension of ".jnlp"), the web browser passes the file to the Java Web Start helper application. Web Start helper application will then automatically download, cache and run the selected Java application.

First Web Start Application

Let's us deploy a normal Swing application over the web using Web Start.

Configuring the Web Server

We need a web server to deliver our Web Start application. First of all, we need to configure it to recognize the Java Web Start MIME type. The MIME type of Web Start JNLP file is "application/x-java-jnlp-file" and the associated file extension is ".jnlp".

Tomcat 6: The MIME type is already defined in the web configuration file "$TOMCAT_HOME/conf/web.xml" as follows:

<mime-mapping>
   <extension>jnlp</extension>
   <mime-type>application/x-java-jnlp-file</mime-type>
</mime-mapping>

Apache Web Server 1.3 / 2.2: Add the following line to the MIME-type configuration file "$APACHE_HOME\conf\mime.types".

application/x-java-jnlp-file     jnlp

The above configuration directs the web server to insert a response header "Content-type: application/x-java-jnlp-file" if a request to a file with extension ".jnlp" is made. The web browser, upon receipt of this "Content-type" response header, will pass the JNLP downloaded to the Web Start helper application.

Prepare the Application to be deployed

Let's deploy our earlier Swing application "SwingCounter" (reproduced below) over the web via Web Start. Note that this is an ordinary standalone Swing application that runs on a desktop.

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
   
public class SwingCounter extends JFrame {
   private JTextField tfCount;
   private int counterValue = 0;
   
   public SwingCounter () {
      Container cp = getContentPane();
      cp.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 15));
      cp.add(new JLabel("Counter"));
      tfCount = new JTextField(10);
      tfCount.setEditable(false);
      tfCount.setText(counterValue + "");
      cp.add(tfCount);
      JButton btnCount = new JButton("Count");
      cp.add(btnCount);
      btnCount.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            counterValue++;
            tfCount.setText(counterValue + "");
         }
      });
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(250,100);
      setTitle("Swing Counter");
      setVisible(true);
   }
   
   public static void main(String[] args) {
      SwingCounter f = new SwingCounter();
   }
}

Compile and execute the application. It is important to note that this program is the same as any other Java standalone applications. In fact, any Java applications that can be run as JAR file can be deployed using Java Web Start.

Web Start applications must be delivered in a set of JAR files. Hence, we have to jar all the resources together using the JDK utility jar as follows, where "swing-counter.jar" is the resultant JAR file.

> jar cfv swing-counter.jar SwingCounter*.class

Take note that the inner class "SwingCount$1.class" is to be included in the JAR file..

Deploy the Application

First, create a network launching JNLP configuration file "SwingCounter.jnlp" as follows:

<?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for SwingCounter Application -->
<jnlp spec="1.0+" codebase="http://host:port/path" href="SwingCounter.jnlp">
  <information>
    <title>Swing Counter Web Start</title>
    <vendor>ME</vendor>
    <description>Swing Counter Web Start</description>
  </information>
  <resources>
    <j2se  version="1.4+" />
    <jar  href="swing-counter.jar" />
  </resources>
  <application-desc main-class="SwingCounter" />
</jnlp>

The "SwingCounter.jnlp" configuration file, as well as the application JAR file "swing-counter.jar", must be kept in the web server and accessible via the URL with codebase at http://host:port/path/ as defined in the JNLP file.

You are now ready to run your first Java Web Start Application. The initial launch of a web start application is via a web browser. Subsequently, you can re-launch the application via web browser, desktop, start menu or Web Start Application Manager.

  1. Start a web browser and either directly reference the JNLP file via http://host:port/path/SwingCounter.jnlp or place the JNLP file as a hyperlink of an HTML file as follows:
    <html>
    <head>
      <title>First Web Start</title>
    </head>
    <body>
      <h1>Web Start Application</h1>
      <a href="SwingCounter.jnlp">Launch "Swing Counter Application"</a>
    </body>
    </html>

  2. Subsequently, you can re-launch the application from the Web Start Application Manager, web browser, or command shell as follows:
    > javaws http://host:port/path/SwingCounter.jnlp
    

    where "javaws" is the Java Web Start program in "$JAVA_HOME\bin\javaws.exe".

For debugging purpose, you could turn on the Web Start Java Console by checking "File" ⇒ "Preferences" ⇒ "Advanced" ⇒ "Show Java Console and Log Output".

Try:

  1. Re-launch the application again.
  2. Start the Web Start Application Manager and run the application.
  3. Delete the application from the local cache using the Application Manager. Re-launch the application.
  4. Stop the Web Server and run the application.
  5. Modify the JNLP file and include <offline-allowed /> within <information> as follows:
    <information>
      ......
      <offline-allowed />
    </information>
    

    Try running the application with the Web Server running, as well as stopped.

  6. Request for unrestricted access by including the following <security> element under the <jnlp> root element:
    <jnlp>
      ......
      <security>
        <all-permissions />
      </security>
    </jnlp>
    
    Try running the application.  Observe and explain the result.
  7. All Java applications that can be executed via JAR files can be deployed using Web Start. Now, try deploying others GUI applications that you have written, following the above steps.

To reduce the file size of the class file (so as to reduce the download time), you can choose not to generate debug information during the compilation process:

> javac –g:none ClassName.java

JAR Files & Web Start

Signing JAR files with a Test Certificate

The Java Web Start application, by default, run inside a "sandbox" with restrictive access to local disks and network. To request for unrestricted access, all the JAR files must be signed. The client will then be prompted to accept the provider's certificate before the application can be started.

JDK provides utilities "keytool" for managing public/private keys and digital certificates and "jarsigner" for signing the JAR files. The step for signing a JAR file with a test certificate is as follows:

  1. Generate a pair of public and private keys (-genkey) for a certain person called provideName (–alias) and keep in a new "keystore" called providerKeyStore (–keystore) as follows:
    > keytool –genkey –keystore providerKeyStore –alias providerName
    
  2. Create a self-signed certificate (-selfcert) for the person providerName, whose public and private keys are kept in the providerKeyStore (-keystore). (A digital certificate contains a person's public key, which is signed by a Certificate Authority (CA)’s private key. A self-signed certificate contains a person's public key, which is signed by his own private key).
    > keytool –selfcert –alias providerName –keystore providerKeyStore
    

    To list the contents of keystore, you can issue:

    > keytool –list –keystore providerKeyStore
    
  3. Finally, use the "jarsigner" utility to sign a JAR file "jarfile.jar" with the test certificate of providerName, which is kept in providerKeyStore (-keystore) as follows:
    > jarsigner –keystore providerKeyStore jarfile.jar providerName
    

Accessing Resources from JAR files

All application resources (such as images, files, native libraries, ResourceBundle and properties-files) must be delivered in JAR files and specified in the <resources> element of the JNLP file. Since these resource are part of the JAR file, the resources can only be loaded into the application using the ClassLoader.getResource() or ClassLoader.getResourceAsStream() (which returns an InputStream for reading the resource). Reading resources from the JAR file is within the sandbox. The JAR files need not be digitally signed.

For examples:

// Get the ClassLoader
ClassLoader cl = this.getClass().getClassLoader();
 
// Load file
BufferedInputStream in1 = new BufferedInputStream(
              cl.getResource("filename").openStream());
in1.read();
// Alternate way to load file
BufferedInputStream in2 = new BufferedInputStream(
              cl.getResourceAsStream("filename"));
in2.read();

// Load images and create icons
Icon saveIcon = new ImageIcon(cl.getResource("images/save.gif"));
...

// ResourceBundle and properties-file, e.g., test.properties
ResourceBundle bundle = ResourceBundle.getBundle("test");
int number = Integer.parseInt(bundle.getString("number"));

 

 

REFERENCES & RESOURCES

Latest version tested: JDK 1.6
Last modified: July 2008