NOTE: Java applets have been deprecated since Java 9 in 2017, and were removed from Java SE (Standard Edition) 11 (18.9), released in September 2018.

This means that, while you may find learning about Java applets to be interesting, it won’t get you far today in practical web applications using Java.

There are various alternatives, but most of them come down to using JavaScript in some way or another.

GWT is an interesting project that you might find useful. It allows you to write Java code using a predetermined set of classes, and basically translate them into JavaScript code for use on the web. It’s open source, and totally free.

Way back when, in the original release of Java, applets were a big deal.  At the time, HTML web pages were regarded as rather static, and any technology that added a dynamic aspect to HTML web pages was considered goodness.

Over the years, however, applets have become less and less important to Java.  Much of this was a result of the browser wars between Netscape and Microsoft, and the negative consequences of those wars still linger today.  Another reason was that other technologies have evolved to make web pages more dynamic.

Many books on Java use applets heavily in their examples.  I have avoided that, because I have found that learning the various quirks and foibles of different web browsers just to get an applet to work tended to get in the way of learning Java itself.  So, most of my examples use Java applications, which are simpler to get working because you don’t have to fight the browser as well as the language.

Applet Security Constraints

Applets run within a browser, subject to the constraints of a security manager.

In JDK 1.0.x, applets loaded over the web were completely constrained:

  • No reading, or writing, or deleting, or getting information about local files.
  • No running another program.
  • No loading of a Java library
  • No connection to a server other than the one the applet was loaded from.
  • etc…

In JDK 1.1.x, and beyond, applets may be trusted as a result of being signed — they may carry a secure certificate that identifies the source of the applet, and verifies that the source may be trusted.  Unfortunately, Netscape’s way of signing applets is not compatible with Microsoft’s way, and vice versa.  This has been solved with the use of the Sun Java Plug-in.

Customizable security levels are already implemented in some browsers, but signed applet support requires JDK 1.1.x support (or above) in the browser.

With each version of Java has come an increased level of granularity in terms of the ability to control what a particular trusted applet is allowed to do.  Initially, with JDK 1.1, applets could be either untrusted, or completely trusted.  Later versions of Java allowed more ability to specify exactly what a trusted applet could, or could not, do.

Today, modern browsers use the Java Plug-in, which allows the browser to support completely up to date versions of Java.  However, this does mean that someone has to download and install the Java Plug-in for some browsers (notably Microsoft Internet Explorer).  Since the Java Plug-in is rather large, this can be a non-trivial task.

Testing Applets

While you’re developing applets, you can try them out in a browser, but debugging is likely to be done within an applet viewer:

  • The JDK comes with a standard appletviewer program
  • Various Java IDEs may provide their own equivalent to appletviewer, and also add the ability to debug applets using their debugger.

The Class Hierarchy

Here’s the class hierarchy for applications and applets:

Object
   Component
      Container
         Window
            Frame  // base for applications
         Panel
            Applet // base for applets
               JApplet

An Applet(and a JApplet) is a kind of Panel, which is a kind of Container, etc.

Not so different from what we’ve seen before, right?

A Simple Applet

Here’s a trivial applet:

package applets;

import java.awt.Container;

import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

public class GreetApplet extends JApplet
{
  public void init()
  {
    Container contentPane = getContentPane();
    JLabel label = 
        new JLabel("Greetings from a Java applet",
                   SwingConstants.CENTER);
    contentPane.add(label);
  }
}

Unfortunately, I can’t show you how it displays in a browser because applets have been removed from Java and from pretty much all browsers.

Note: Versions are important when writing applets. For example, when I first wrote the above applet, I wrote it and compiled it using JDK 1.5 .  However, when I tried it in one of my browsers that had a Java 1.4 plug-in, my browser failed to load the applet successfully.  I looked in the Java Plug-in’s Console, and it told me that it had encountered an error:

java.lang.UnsupportedClassVersionError: applets/GreetApplet (Unsupported major.minor version 49.0)

Self-descriptive message, don’t you think? When I investigated further, I discovered that I could not run the code I had written under JDK 1.5 using a Java Plug-in 1.4 (or earlier).  So, I changed the source code to ensure I wasn’t using any JDK 1.5 specific features, and then compiled it under JDK 1.4.  The resulting version now runs using both the 1.4 and 1.5 versions of the Java Plug-in.

HTML Tags for Applets

To embed an applet within a web page, you must use an appropriate set of HTML tags:

Here’s the HTML for a very simple web page with an embedded applet:

<html>
<head>
<title>I'm a Java-enabled Web Page!</title>
</head>
<body>
 Here's the Java applet:
 <applet code="MyApplet.class"
	 width="300"
	 height="200"
 >
 Sorry, you're out of luck!
 Your browser doesn't support Java.
 </applet>
</body>
</html>

As you can see, there’s a single tag, <applet> ... </applet> which has a number of attributes that can be specified.

Here are the named attributes for the <applet> tag for JDK 1.0.x:

Attribute nameRequired?Description
CODE="foo.class"YesSpecifies the name of the applet’s .class file.
WIDTH=pixelsYesSpecifies the width of the applet window
HEIGHT=pixelsYesSpecifies the height of the applet window
CODEBASE="path"NoSpecifies where to find the .class files, relative to the location of the enclosing HTML page.
NAME="applet-name"NoSpecifies the name of the applet (used to distinguish it from other applets on the same page).
ALIGN=LEFTNoPlaces the applet at the left margin of the page. Text that follows goes in the space to the right of the applet.
ALIGN=RIGHTNoPlaces the applet at the right margin of the page. Text that follows goes in the space to the left of the applet
ALIGN=BOTTOMNoPlaces the bottom of the applet at the bottom of the text in the current line.
ALIGN=TOPNoPlaces the top of the applet with the top of the current line.
ALIGN=TEXTTOPNoPlaces the top of the applet with the top of the text in the current line.
ALIGN=MIDDLENoPlaces the middle of the applet with the baseline of the current line.
ALIGN=ABSMIDDLENoPlaces the middle of the applet with the middle of the current line.
ALIGN=BASELINENoPlaces the bottom of the applet with the baseline of the current line.
ALIGN=ABSBOTTOMNoPlaces the bottom of the applet with the bottom of the current line.
VSPACE=pixelsNoCreates a vertical margin around the applet .
HSPACE=pixelsNoCreates a horizontal margin around the applet.

Here are the <applet> tag attributes added for JDK 1.1.x:

Attribute nameRequired?Description
ARCHIVE="jar-file"NoSpecifies the name of a Java archive (JAR) file that contain classes and other resources for the applet.
OBJECT="obj-file"NoSpecifies the name of a file that contains the serialized applet object.

Adding Package & Directory Specifications

The above HTML example is very basic:

  • It specifies an applet whose .class file is in the same directory as its enclosing HTML page file.
  • The class whose .class file is being used is in the default package.

Think of the CODEBASE attribute as specifying a kind of CLASSPATH for the applet. The same kind of rules apply to applets as apply to applications, when you start dealing with classes within packages.

To specify an applet whose .class file is in subdirectory classes, and whose class is in the default package:

<html>
<head>
<title>I'm a Java-enabled Web Page!</title>
</head>
<body>
 Here's the Java applet:
 <applet code="MyApplet.class"
	 codebase="classes"
	 width="300"
	 height="200"
 >
 Sorry, you're out of luck!
 Your browser doesn't support Java.
 </applet>
</body>
</html>

To specify an applet whose class is in the package myPackage:

&lt;html>
&lt;head>
&lt;title>I'm a Java-enabled Web Page!&lt;/title>
&lt;/head>
&lt;body>
 Here's the Java applet:
 &lt;applet code="myPackage.MyApplet.class"
         codebase="classes"
	 width="300"
	 height="200"
 >
 Sorry, you're out of luck!
 Your browser doesn't support Java.
 &lt;/applet>
&lt;/body>
&lt;/html>

and the .class file must be in subdirectory below where the document is:

classes/myPackage

The Applet Life Cycle

Here is a state transition diagram showing the possible states of an applet, during its lifetime:

The four applet methods that cause state transitions are:

MethodDescription
init()Called when the applet is first loaded into the browser. Performs applet initialization. Called once only.
start()Called after the init() method has completed. Also called when the browser opens the page again after having read other pages. Can be called many times.
stop()Called when the browser moves off the page. Can be called many times.
destroy()Called with the applet is about to be unloaded from the browser. Performs resource cleanup. Called once.

Multimedia & URLs

Multimedia includes:

  • images
  • audio
  • video
  • etc…

A URL (Uniform Resource Locator) is a description of a resource on the Internet. Here is an absolute URL:

protocol://host.domain[:port]/path/filename

where protocol is one of:

ProtocolDescription
filea file on your local system
ftpa file on an anonymous FTP server
httpa file on a World Wide Web server
gophera file on a Gopher server
WAISa file on a WAIS server
newsa Usenet newsgroup
telneta connection to a Telnet-based service
etc.other, often application-specific, protocols

You can also use a mailto protocol:

mailto:president@whitehouse.gov

The :port is generally omitted, because each protocol has its own default port number.  However, it is sometimes required when a server is using an non-standard port number.

Here’s a typical example:

http://www.ncsa.uiuc.edu/General/Internet/WWW/HTMLPrimer.html

Another form of URL is a relative URL. For example:

data/planets.dat

which is relative to some other URL.

For more information about URLs, see:

http://www.ncsa.uiuc.edu/demoweb/url-primer.html

The Java URL Class

Java’s java.net.URL class encapsulates URLs. It has constructors:

URL(String absURL)
URL(URL baseURL, String relURL)
URL(String protocol, String host, String file)
URL(String protocol, String host, int port, String file)

Each of these constructors throws a MalformedURLException if the syntax for the resulting URL is incorrect. You must write code that is prepared for this exception:

try
{
    String url = "http://java.sun.com";
    URL u = new URL(url);
    // ...
}
catch (MalformedURLException e)
{
    // Deal with the exception...
}

getDocumentBase() and getCodeBase()

These methods of the javax.swing.JApplet (and java.applet.Applet) class return the following:

MethodDescription
getDocumentBase()returns the URL of the HTML file that contains the applet
getCodeBase()returns the URL of the applet

getImage() and getAudioClip()

These methods of the javax.swing.JApplet (and java.applet.Applet) class return the specified image and audio clip, respectively. 

For example:

package applets;

import java.applet.Applet;
import java.applet.AudioClip;

import java.awt.BorderLayout;
import java.awt.Color;

import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.JApplet;
import javax.swing.JLabel;

import multimedia.ImagePanel;

public class MultimediaApplet extends JApplet
{
  public void init()
  {
    // First, create the image part of the GUI
    URL[] imageURLs = gatherImageURLs();
    getContentPane().add(new ImagePanel(imageURLs),
                         BorderLayout.CENTER);
    
    // Next, a label indicating the state of the audio part
    m_soundLabel = new JLabel("Loading audio clip...");
    m_soundLabel.setOpaque(true);
    m_soundLabel.setBackground(Color.WHITE);
    getContentPane().add(m_soundLabel, BorderLayout.SOUTH);
    
    // Load the audio clip
    loadAudioClip("audio/yahoo1.au");
    
    if (m_sound == null)
    {
      m_soundLabel.setText("No audio clip found...");
      m_soundLabel.setForeground(Color.RED);
    }
    else
    {
      m_soundLabel.setText("Playing audio clip...");
    }
  }
  
  public void start()
  {
    if (m_sound == null)
    {
      System.err.println("No audio clip to play!");
    }
    else
    {
      m_sound.play();
    }
  }
  
  private URL[] gatherImageURLs()
  {
    URL[] imageURLs = new URL[2];
    
    // Get the URL of applet
    URL baseURL = getCodeBase();
    System.out.println("CodeBase: " + baseURL);
    
    // Now get the URL for the first image file, below that directory
    URL imageURL = null;
    try
    {
      imageURL = new URL(baseURL, "images/bleye.gif");
      
      // Set in the first image URL.
      imageURLs[0] = imageURL;
      
      // The second image is on the web
      imageURLs[1] = new URL(
          "http://www.rivier.edu/faculty/bhiggs/web/cs585aweb/images/monalisa.jpg");
    }
    catch (MalformedURLException mue)
    {
      // Something wrong with our URL handling
      mue.printStackTrace();
    }
    
    return imageURLs;
  }
  
  private void loadAudioClip(String path)
  {
    AudioClip clip = null;
    URL baseURL = getCodeBase();
    System.out.println("Audio clip baseURL: " + baseURL);
    URL audioClipURL = null;
    try
    {
      audioClipURL = new URL(baseURL, path);
      System.out.println("Audio clip URL: " + audioClipURL);
      clip = Applet.newAudioClip(audioClipURL);
    }
    catch (MalformedURLException mue)
    {
      mue.printStackTrace();
    }
    m_sound = clip;
    System.out.println("Audio clip loaded.");
  }
  
  ///////// Data //////////////
  private JLabel m_soundLabel;
  private AudioClip m_sound = null;
}

package multimedia;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;

import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ImagePanel extends JPanel
{
  public ImagePanel(final URL[] imageURLs)
  {
    setBackground(Color.WHITE);
    setLayout(new BorderLayout());
    
    // Indicate that we're loading images,
    // which may take a long time.
    JLabel statusLabel = new JLabel("Loading Images...",
        JLabel.CENTER);
    statusLabel.setForeground(Color.BLACK);
    add(statusLabel, BorderLayout.CENTER);
    
    // Load the images in a separate thread to avoid
    // hanging up this thread waiting for load completion.
    Thread loader = new Thread()
    {
      public void run()
      {
        loadImages(imageURLs);
        // When done, cause a repaint from the 
        // event dispatcher thread
        SwingUtilities.invokeLater( new Runnable()
        {
          public void run()
          {
            // Remove the "Loading images..." label
            ImagePanel.this.removeAll();
            // and cause the images to display
            ImagePanel.this.repaint();
          }
        }
        );
      }
    };
    // Start the loader thread
    loader.start();
  }
  
  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    
    if (m_imagesLoaded)
    {
      g.setColor(Color.BLACK);
      int x = 5;
      int y = 5;
      for (int i = 0; i < m_image.length; i++)
      {
        if (m_image[i] != null)
        {
          m_image[i].paintIcon(this, g, x, y);
          x += m_image[i].getImage().getWidth(this) + 5;
        }
        else
        {
          g.setColor(Color.RED);
          g.drawString("No image found", x, y);
        }
      }
    }
  }
  
  private void loadImages(URL[] imageURLs)
  {
    m_image = new ImageIcon[imageURLs.length];
    for (int i = 0; i < imageURLs.length; i++)
    {
      m_image[i] = new ImageIcon(imageURLs[i]);
    }
    m_imagesLoaded = true;
  }
  
  //// Private data /////
  private ImageIcon[] m_image;
  private boolean m_imagesLoaded;
}

Again, I can’t show you the result because Java applets have been deprecated and removed from Java

Applet Context

An applet runs inside a browser or applet viewer.

An applet running within a browser can ask the browser to do things for it:

  • Fetch an audio clip
  • Show a short message in the status line
  • Show a different web page

The browser can perform these requests or ignore them.

  • To communicate with the browser, an applet calls the java.applet.Applet.getAppletContext() method, which returns an object that implements an interface of type java.applet.AppletContext.
  • Think of AppletContext as a communication path between the applet and the browser.
  • AppletContext provides the following methods:
MethodDescription
void showStatus(String message)Shows the message in the status line of the browser
Enumeration getApplets()Returns an enumeration of all the applets in the same context (same web page)
Applet getApplet(String name)Returns the applet in the current context with the specified name (null if none exists)
void showDocument(URL url)Shows a new web page in the browser, displacing the current page.
void showDocument(URL url, String target)Shows a new web page in the browser, specifying the target frame
(“_self”, “_parent”, “_top”, “_blank”, or <frame-name>)
Image getImage(URL url)Returns an image object that encapsulates the image specified by the URL
AudioClip getAudioClip(URL url)Returns an AudioClip object that encapsulates the sound file specified by the URL.

Converting Applications to Applets

A Java program can be both an applet and an application:

// ...
public class AppletApplication extends JApplet
{
    public void init() 
    { ... }
    
    // ...
    
    public static void main(String[] args) 
    { ... }
}

To make it work, the main method must create a frame for the applet to execute in.

It’s convenient to create a frame to use for this purpose:

// ...
public class AppletFrame extends JFrame
{
    public AppletFrame(JApplet applet, int width, int height)
    {
        setTitle(applet.getClass.getName());
        setSize(width, height);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JPanel panel = new JPanel( new BorderLayout() );
        getContentPane().add(panel);

        panel.add(applet, BorderLayout.CENTER); // Add applet to frame

        applet.init();		// Init the applet
        setVisible(true);
        applet.start();		// Start the applet
    }

    // ...
}

So the main method of the AppletApplication should do the following:

// ...
public class AppletApplication extends JApplet
{
    public void init() 
    { ... }
    
    // ...
    
    public static void main(String[] args) 
    {
        new AppletFrame(new AppletApplication(), 620, 400);
    }
}

Unfortunately, this is not sufficient. If the applet tries to execute code like:

getAppletContext()

because there is no applet context in the AppletFrame.The fix is to implement two interfaces in AppletFrame:

  • AppletStub
  • AppletContext
// ...
public class AppletFrame extends JFrame
	implements AppletStub, AppletContext
{
    // AppletStub methods
    public boolean isActive() { return true; }
    public URL getDocumentBase() { return null; }
    public URL getCodeBase() { return null; }
    public String getParameter(String name) { return ""; }
    public AppletContext getAppletContext() { return this; }
    public void appletResize(int width, int height) {}

    // AppletContext methods
    public AudioClip getAudioClip(URL url) { return null; }
    public Image getImage(URL url) { return null; }
    public Applet getApplet(String name) { return null; }
    public Enumeration getApplets() { return null; }
    public void showDocument(URL url) {}
    public void showDocument(URL url, String target) {}
    public void showStatus(String status) {}

    public AppletFrame(Applet applet, int width, int height)
    {
        setTitle(applet.getClass.getName());
        setSize(width, height);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JPanel panel = new JPanel( new BorderLayout() );
        getContentPane().add(panel);

        panel.add(applet, BorderLayout.CENTER); // Add applet to frame

        applet.setStub(this);	// Set up the AppletStub
        applet.init();		// Init the applet
        setVisible(true);
        applet.start();		// Start the applet
    }

    // ...
}

Another possibility is to use inheritance to allow any applet to be executable as an application:

public class CalculatorAppletApplication
		extends AppletApplication
{
    public static void main(String[] args)
    {
        new AppletFrame(new CalculatorApplet(), 150, 100);
    }
}