Chapter 18. Applets

THIS chapter talks about the basics of applets, advantages of applets over applications, how to load applets in a Web page, how to convert applications to applets, and how applets work.

An applet is a special kind of Java program that a browser enabled with Java technology can download from the Internet and run. An applet is typically embedded inside a Web page and runs in the context of the browser. An applet must be a subclass of the java.applet.Applet class, which provides the standard interface between the applet and the browser environment.

Swing provides a special subclass of Applet, called javax.swing.JApplet, which should be used for all applets that use Swing components to construct their GUIs.

By calling certain methods, a browser manages an applet’s life cycle if an applet is loaded in a Web page.

• Life Cycle of an Applet

Basically, there are four methods in the Applet class on which any applet is built:

  • initThis method is intended for whatever initialization is needed for your applet. It is called after the param attributes of the applet tag.

  • startThis method is automatically called after init method. It is also called whenever user returns to the page containing the applet after visiting other pages.

  • stopThis method is automatically called whenever the user moves away from the page containing applets. You can use this method to stop an animation.

  • destroyThis method is only called when the browser shuts down normally.

Thus, the applet can be initialized once and only once, started and stopped one or more times in its life, and destroyed once and only once.

For more information, please refer to The Life Cycle of an Applet section (page 547).

• When to Write Applets versus Applications

In the early days of Java, one of the critical advantages that Java applets had over Java applications was that applets could be easily deployed over the Web while Java applications required a more cumbersome installation process. Additionally, since applets are downloaded from the Internet, by default they have to run in a restricted security environment, called the “sandbox,” to ensure they don’t perform any destructive operations on the user’s computer, such as reading/writing to the filesystem.

However, the introduction of Java Web Start (see Chapter 17) has made it possible for Java applications to also be easily deployed over the Web, as well as run in a secure environment. This means that the predominant difference between a Java applet and a Java application is that an applet runs in the context of a Web browser, being typically embedded within an HTML page, while a Java application runs stand-alone, outside the browser. Thus, applets are particularly well suited for providing functions in a Web page that require more interactivity or animation than HTML can provide, such as a graphical game, complex editing, or interactive data visualization. The end user is able to access the functionality without leaving the browser.

• Loading Applets in a Web Page

In order to load an applet in a Web page, you must specify the applet class with appropriate applet tags. A simple example is below:

<applet code=AppletWorld.class width="200" height="200">
</applet>

For development and testing purposes, you can run your applet using the lightweight appletviewer application that comes with the JDK. For example, if AppletWorld.html is the HTML file name, then you run the command as:

appletviewer AppletWorld.html

Once you know your applet runs within the appletviewer, it is important to test your applet running in a Web browser by loading the applet’s Web page into the browser window. The browser can retrieve the class files either from the Internet or from the local working directory used during development. If you make changes to your applet’s code while it is loaded in the browser, then you must recompile the applet and press the Shift + Reload button in the browser to load the new version.

This chapter is intended to get you started with applets and Java Plug-in, and it does not include all available documentation. For more information about applets, see the Java Plug-in Developer Guide.[1]

Getting Started with Applets

Run the HelloWorld applet[2] in the online tutorial or compile and run the applet yourself (Figure 18.1). It is a simple Java class that prints the string “Hello World” in small rectangle.

A screenshot of the HelloWorld applet.

Figure 18.1. A screenshot of the HelloWorld applet.

Following is the source code for the HelloWorld applet:[3]

import javax.swing.JApplet;
import java.awt.Graphics;

public class HelloWorld extends JApplet {
  public void paint(Graphics g) {
    g.drawRect(0, 0,
               getSize().width - 1,
               getSize().height - 1);
    g.drawString("Hello world!", 5, 15);
  }
}

An applet such as this is typically managed and run by Java Plug-in. Java Plug-in, which is automatically included when you download the Java SE Runtime Environment (JRE), extends the functionality of a Web browser, allowing applets to be run under Sun’s Java SE Runtime Environment (JRE) rather than the Java Runtime Environment that comes with the Web browser. It works with the Mozilla family of browsers and with Internet Explorer.

• Converting Applications to Applets

An application is a stand-alone program consisting of at least one class with a main method. Applets differ significantly from applications. First, applets do not have a main method that is automatically called to begin the program. Instead, several methods are called at different points in the execution of an applet. The difference between Java applets and applications lies in how they are run. Applications are usually run by loading the application’s main class file with a Java interpreter, such as the java tool in the JDK 6.

The basic steps to follow to convert an application program into an applet program are:

  • You need to create a subclass of java.applet.Applet in which you override the init method to initialize your applet’s resources the same way the main method initializes the application’s resources.

  • init might be called more than once and should be designed accordingly. Moreover, the top-level Panel needs to be added to the applet in init; usually it was added to a Frame in main. That’s it!

You will understand how to convert an application program into an applet by going through a sample application program SwingUI.java[4] and its corresponding applet program.[5]

When you compare these two programs, you may come up with the following major differences between the two:

  • The applet class is declared public so appletviewer can access it.

  • The applet class descends from Applet/JApplet, and the application class descends from Frame/JFrame.

  • The applet version has no main method.

  • The application constructor is replaced in the applet by start and init methods.

  • GUI components are added directly to the Applet, whereas in an application, GUI components are added to the content pane of its JFrame object.

Extending Applet or JApplet

The first bold line of the following listing begins a block that defines the HelloWorld class:

import javax.swing.JApplet;
import java.awt.Graphics;

public class HelloWorld extends JApplet {
  public void paint(Graphics g) {
    g.drawRect(0, 0,
               getSize().width - 1,
               getSize().height - 1);
    g.drawString("Hello world!", 5, 15);
  }
}

Applets inherit a great deal of functionality from the Applet or JApplet class, including the abilities to communicate with the browser and to present a graphical user interface (GUI) to the user.

An applet that will be using GUI components from Swing (Java’s GUI toolkit) should extend the javax.swing.JApplet base class, which provides the best integration with Swing’s GUI facilities.

JApplet provides the same “RootPane” top-level component structure as Swing’s JFrame and JDialog components, whereas Applet provides just a simple panel. See How to Use Root Panes[6] for more details on how to utilize this feature.

An applet may extend java.applet.Applet when it makes no use of Swing’s GUI components. This may be the case if the applet does all its own rendering using the Java graphics libraries (such as with graphing or gaming) and/or uses only AWT components.

The Life Cycle of an Applet

Run the Simple applet[7] (Figure 18.2).

A screenshot of the Simple applet.

Figure 18.2. A screenshot of the Simple applet.

The following is the source code for the Simple.[8] The Simple applet displays a descriptive string whenever it encounters a major milestone in its life, such as when the user first visits the page that the applet is on. The pages that follow use the Simple applet and build upon it to illustrate concepts that are common to many applets. If you find yourself baffled by the Java source code, you might want to go to Chapter 2 to learn about the language.

/*
 * Java SE 6 Version
 */

import java.applet.Applet;
import java.awt.Graphics;

// No need to extend JApplet, since we don't add
// any components; we just paint.
public class Simple extends Applet {

  StringBuffer buffer;

  public void init() {
    buffer = new StringBuffer();
    addItem("initializing... ");
  }

  public void start() {
    addItem("starting... ");
  }

  public void stop() {
    addItem("stopping... ");
  }

  public void destroy() {
    addItem("preparing for unloading...");
  }

  private void addItem(String newWord) {
    System.out.println(newWord);
    buffer.append(newWord);
    repaint();
  }

  public void paint(Graphics g) {
    // Draw a Rectangle around the applet's display area.
    g.drawRect(0, 0,
    getWidth() - 1,
    getHeight() - 1);

    // Draw the current string inside the rectangle.
    g.drawString(buffer.toString(), 5, 15);
  }
}

Note

In this example, we extend the Applet class, not the Swing JApplet class, as we do not need to add Swing components to this applet.

Loading the Applet

You should see “initializing … starting … ” above, as the result of the applet being loaded. When an applet is loaded, here’s what happens:

  • An instance of the applet’s controlling class (an Applet subclass) is created.

  • The applet initializes itself.

  • The applet starts running.

Leaving and Returning to the Applet’s Page

When the user leaves the page—for example, to go to another page—the browser stops the applet. When the user returns to the page, the browser starts the applet.

Browser Note

Some browsers reload the applet when you return to its page. In at least one browser, a bug exists where an applet can initialize itself more than once without being reloaded.

Reloading the Applet

Some browsers let the user reload applets, which consists of unloading the applet and then loading it again. Before an applet is unloaded, it’s given the chance to stop itself and then to perform a final cleanup, so that the applet can release any resources it holds. After that, the applet is unloaded and then loaded again, as described in the Loading the Applet section (page 549).

Try This

If your browser or other applet viewer lets you easily reload applets, reload the applet. Look at the Displaying Diagnostics to the Standard Output and Error Streams section (page 583) to see what happens when you reload the applet. (See the Displaying Short Status Strings section, page 561, for information about the standard output.) You should see “stopping …” and “preparing for unloading …” when the applet is unloaded. You can’t see this in the applet GUI because the applet is unloaded before the text can be displayed. When the applet is reloaded, you should see “initializing …” and “starting …”, just like when you loaded the applet for the first time.

Quitting the Browser

When the user quits the browser (or whatever application is displaying the applet), the applet has the chance to stop itself and do final cleanup before the browser exits.

Summary

An applet can react to major events in the following ways:

  • It can initialize itself.

  • It can start running.

  • It can stop running.

  • It can perform a final cleanup, in preparation for being unloaded.

The next section describes the four applet methods that correspond to these four types of reactions.

Methods for Milestones

The Simple applet, like every other applet, features a subclass of the Applet class. The Simple class overrides four Applet methods so that it can respond to major events:

  • initTo initialize the applet each time it’s loaded (or reloaded).

  • startTo start the applet’s execution, such as when the applet is loaded or when the user revisits a page that contains the applet.

  • stopTo stop the applet’s execution, such as when the user leaves the applet’s page or quits the browser.

  • destroyTo perform a final cleanup in preparation for unloading.

Following is the interface for these methods:

public class Simple extends JApplet {
  ...
  public void init() { ... }
  public void start() { ... }
  public void stop() { ... }
  public void destroy() { ... }
  ...
}

The init, start, stop, and destroy methods are discussed and used throughout this tutorial. For more information, you can also refer to the JApplet API Specification.[9]

Overriding These Methods

Not every applet needs to override every one of these methods. Some very simple applets override none of them. For example, the “Hello World” applet (page 6) doesn’t override any of these methods, since it doesn’t do anything except draw itself.

The “Hello World” applet just displays a string once, using its paint method. (The paint method is described on page 552.) Most applets, however, do more.

The init Method

The init method is useful for one-time initialization that doesn’t take very long. In general, the init method should contain the code that you would normally put into a constructor. The reason applets shouldn’t usually have constructors is that an applet isn’t guaranteed to have a full environment until its init method is called. For example, the Applet image-loading methods simply don’t work inside of an applet constructor. The init method, on the other hand, is a great place to call the image-loading methods, since the methods return quickly.

Browser Note

Some browsers sometimes call the init method more than once after the applet has been loaded. See The Life Cycle of an Applet section (page 547) for more details.

The start Method

Every applet that does something after initialization (except in direct response to user actions) must override the start method. The start method either performs the applet’s work or (more likely) starts up one or more threads to perform the work. You’ll learn more about threads in the Threads in Applets section (page 585). You’ll learn more about handling the events that represent user actions in the Methods for Drawing and Event Handling section (page 552).

The stop Method

Most applets that override start should also override the stop method. The stop method should suspend the applet’s execution so that it doesn’t take up system resources when the user isn’t viewing the applet’s page. For example, an applet that displays animation should stop trying to draw the animation when the user isn’t looking at it.

The destroy Method

Many applets don’t need to override the destroy method, since their stop method (which is called before destroy) does everything necessary to shut down the applet’s execution. However, destroy is available for applets that need to release additional resources.

Note

You should keep implementations of the destroy method as short as possible, because there is no guarantee that this method will be completely executed. The Java Virtual Machine might exit before a long destroy method has completed.

Methods for Drawing and Event Handling

Using the paint Method

To draw the applet’s representation within a browser page, you use the paint method.

For example, the Simple applet defines its onscreen appearance by overriding the paint method:

public void paint(Graphics g) {
  // Draw a Rectangle around the applet's display area.
  g.drawRect(0, 0,
    getWidth() - 1,
    getHeight() - 1);

  // Draw the current string inside the rectangle.
  g.drawString(buffer.toString(), 5, 15);
}

Applets inherit the paint method from the Abstract Window Toolkit (AWT) Container class.

Handling Events

Applets inherit a group of event-handling methods from the Container class.

The Container class defines several methods, such as processKeyEvent and processMouseEvent, for handling particular types of events, and then one catch-all method called processEvent.

To react to an event, an applet must override the appropriate event-specific method. For example, the following program, SimpleClick,[10] implements a MouseListener and overrides the mouseClicked method:

/*
 * Java(TM) SE 6 version.
 */

import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.applet.Applet;
import java.awt.Graphics;

// No need to extend JApplet, since we don't add
// any components; we just paint.
public class SimpleClick extends Applet
    implements MouseListener {

  StringBuffer buffer;

  public void init() {
    addMouseListener(this);
    buffer = new StringBuffer();
    addItem("initializing... ");
  }

  public void start() {
    addItem("starting... ");
  }

  public void stop() {
    addItem("stopping... ");
  }

  public void destroy() {
    addItem("preparing for unloading...");
  }

  void addItem(String newWord) {
    System.out.println(newWord);
    buffer.append(newWord);
    repaint();
  }
  public void paint(Graphics g) {
    // Draw a Rectangle around the applet's display area.
    g.drawRect(0, 0,
               getWidth() - 1,
               getHeight() - 1);

    // Draw the current string inside the rectangle.
    g.drawString(buffer.toString(), 5, 15);
  }

  // The following empty methods could be removed
  // by implementing a MouseAdapter (usually done
  // using an inner class).
  public void mouseEntered(MouseEvent event) {
  }
  public void mouseExited(MouseEvent event) {
  }
  public void mousePressed(MouseEvent event) {
  }
  public void mouseReleased(MouseEvent event) {
  }

  public void mouseClicked(MouseEvent event) {
    addItem("click!... ");
  }
}

Run the resulting applet[11] (Figure 18.3). When you click within its rectangle, it displays the word “click! …”.

A screenshot of the SimpleClick applet.

Figure 18.3. A screenshot of the SimpleClick applet.

Methods for Adding UI Components

The Simple applet’s display code (implemented in its paint method) is flawed: It doesn’t support scrolling. Once the text it displays reaches the end of the display rectangle, you can’t see any new text. Figure 18.4 shows an example of the problem.

The output from the Simple applet demo showing the lack of scrolling.

Figure 18.4. The output from the Simple applet demo showing the lack of scrolling.

The simplest cure for this problem is to use a pre-made user interface (UI) component that has the right behavior.

Note

This section glosses over many details. To really learn about using UI components, read Creating a GUI with JFC/Swing.[12]

Pre-Made UI Components

Swing supplies the following UI components (the class that implements each component is listed in parentheses):

  • Buttons (javax.swing.JButton)

  • Checkboxes (javax.swing.JCheckBox)

  • Single-line text fields (javax.swing.JTextField)

  • Larger text display and editing areas (javax.swing.JTextArea)

  • Labels (javax.swing.JLabel)

  • Lists (javax.swing.JList)

  • Pop-ups (javax.swing.Popup)

  • Scrollbars (javax.swing.JScrollBar)

  • Sliders (javax.swing.JSlider)

  • Drawing areas (java.awt.Canvas)

  • Menus (javax.swing.JMenu, javax.swing.JMenuBar, javax.swing. JMenuItem, javax.swing.JCheckBoxMenuItem)

  • Containers (javax.swing.JPanel, javax.swing.JWindow, and its subclasses)

Methods for Using UI Components in Applets

Because the JApplet class inherits from the AWT Container class, it’s easy to add components to applets and to use layout managers to control the components’ onscreen positions. Here are some of the Container methods an applet can use:

  • addAdds the specified Component.

  • removeRemoves the specified Component.

  • setLayoutSets the layout manager.

Adding a Non-Editable Text Field to the Simple Applet

To make the Simple applet use a scrolling, non-editable text field, we can use the JTextField class. Here is the revised ScrollingSimple class:[13]

/*
 * Java(TM) SE 6 version.
 */

import javax.swing.JApplet;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

// Since we're adding a Swing component, we now need to
// extend JApplet. We need to be careful to access
// components only on the event-dispatching thread.
public class ScrollingSimple extends JApplet {

  JTextField field;

  public void init() {
    // Execute a job on the event-dispatching thread:
    // creating this applet's GUI.
    try {
        SwingUtilities.invokeAndWait(new Runnable() {
          public void run() {
            createGUI();
          }
        });
    } catch (Exception e) {
        System.err.println("createGUI didn't " +
                           "successfully complete");
    }
    addItem(false, "initializing... ");
  }

  private void createGUI() {
    // Create the text field and make it uneditable.
    field = new JTextField();
    field.setEditable(false);

    // Set the layout manager so that the text field will be
    // as wide as possible.
    setLayout(new java.awt.GridLayout(1,0));

    // Add the text field to the applet.
    add(field);
  }
  public void start() {
    addItem(false, "starting... ");
  }

  public void stop() {
    addItem(false, "stopping... ");
  }

  public void destroy() {
    addItem(false, "preparing for unloading...");
    cleanUp();
  }

  private void cleanUp() {
    // Execute a job on the event-dispatching thread:
    // taking the text field out of this applet.
    try {
        SwingUtilities.invokeAndWait(new Runnable() {
          public void run() {
            remove(field);
          }
        });
    } catch (Exception e) {
        System.err.println("cleanUp didn't " +
                           "successfully complete");
    }
    field = null;
  }

  private void addItem(boolean alreadyInEDT, String newWord) {
    if (alreadyInEDT) {
        addItem(newWord);
    } else {
        final String word = newWord;
        // Execute a job on the event-dispatching thread:
        // invoking addItem(newWord).
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
              public void run() {
                addItem(word);
              }
            });
        } catch (Exception e) {
            System.err.println("addItem didn't " +
                               "successfully complete");
        }
    }
  }
  // Invoke this method ONLY from the event-dispatching thread.
  private void addItem(String newWord) {
    String t = field.getText();
    System.out.println(newWord);
    field.setText(t + newWord);
  }
}

The createGUI method creates an uneditable text field (a JTextField instance). It sets the applet’s layout manager to one that makes the text field as wide as possible (you can learn about layout managers in Laying Out Components within a Container[14]) and then adds the text field to the applet.

Run the resulting applet[15] (Figure 18.5).

A screenshot of the ScrollingSimple applet.

Figure 18.5. A screenshot of the ScrollingSimple applet.

What Applets Can and Can’t Do

This section gives an overview of both the restrictions applets face and the special capabilities they have. You will find more details in the Security Restrictions section (page 578).

Security Restrictions

Every browser implements security policies to keep applets from compromising system security. This section describes the security policies that current browsers adhere to. However, the implementation of the security policies differs from browser to browser. Also, security policies are subject to change. For example, if a browser is developed for use only in trusted environments, then its security policies will likely be much more lax than those described here.

Current browsers impose the following restrictions on any applet that is loaded over the network:

  • An applet cannot load libraries or define native methods.

  • It cannot ordinarily read or write files on the host that’s executing it.

  • It cannot make network connections except to the host that it came from.

  • It cannot start any program on the host that’s executing it.

  • It cannot read certain system properties.

  • Windows that an applet brings up look different than windows that an application brings up.

Each browser has a SecurityManager object that implements its security policies. When a SecurityManager detects a violation, it throws a SecurityException. Your applet can catch this SecurityException and react appropriately.

Applet Capabilities

The java.applet package provides an API that gives applets some capabilities that applications do not have.

Here are some other things that current browers and other applet viewers let applets do:

  • Applets can usually make network connections to the host they came from.

  • Applets running within a Web browser can easily cause HTML documents to be displayed.

  • Applets can invoke public methods of other applets on the same page.

  • Applets that are loaded from the local file system (from a directory in the user’s CLASSPATH) have none of the restrictions that applets loaded over the network do.

Taking Advantage of the Applet API

The applet API lets you take advantage of the close relationship that applets have with Web browsers. The API is provided by the javax.swing.JApplet class and the java.applet.AppletContext interface.

Applets can use these APIs to do the following:

  • Be notified by the browser of milestones.

  • Load data files specified relative to the URL of the applet or the page in which it is running.

  • Display short status strings.

  • Make the browser display a document.

  • Find other applets running in the same page.

  • Play sounds.

  • Get parameters specified by the user in the <APPLET> tag.

This section discusses each of these topics in turn, except for the milestone methods (init, start, and so on), which are explained in the Methods for Milestones section (page 550). For information about how to use non-applet-specific APIs in an applet, see the Practical Considerations When Writing Applets section (page 578).

Finding and Loading Data Files

Whenever an applet needs to load some data from a file that’s specified with a relative URL (a URL that doesn’t completely specify the file’s location), the applet usually uses either the code base or the document base to form the complete URL.

The code base, returned by the JApplet getCodeBase method, is a URL that specifies the directory from which the applet’s classes were loaded.

The document base, returned by the JApplet getDocumentBase method, specifies the directory of the HTML page that contains the applet.

Unless the <APPLET> tag specifies a code base, both the code base and document base refer to the same directory on the same server.

Data that the applet might need, or needs to rely on as a backup, is usually specified relative to the code base. Data that the applet developer specifies, often by using parameters, is usually specified relative to the document base.

Note

For security reasons, browsers limit the URLs from which untrusted applets can read. For example, most browsers don’t allow untrusted applets to use “..” to get to directories above the code base or document base. Also, since untrusted applets can’t read files except those on the applet’s originating host, the document base isn’t generally useful if the document and the untrusted applet are on different servers.

The JApplet class defines convenient forms of image-loading and sound-loading methods that let you specify images and sounds relative to a base URL. For example, assume an applet is set up with one of the directory structures shown in Figure 18.6.

Two directory structures showing the image files and class files in separate locations, with different structures.

Figure 18.6. Two directory structures showing the image files and class files in separate locations, with different structures.

To create an Image object using the a.png image file under imgDir, the applet can use the following code:

Image image = getImage(getCodeBase(), "imgDir/a.png");

Displaying Short Status Strings

All browsers allow applets to display a short status string. All applets on the page, as well as the browser itself, share the same status line.

You should never put crucial information in the status line. If many users might need the information, it should instead be displayed within the applet area. If only a few sophisticated users might need the information, consider displaying the information on the standard output (see the Displaying Diagnostics to the Standard Output and Error Streams section, page 583).

The status line is not usually very prominent, and it can be overwritten by other applets or by the browser. For these reasons, it’s best used for incidental, transitory information. For example, an applet that loads several image files might display the name of the image file it’s currently loading.

Applets display status lines with the showStatus[16] method, inherited in the JApplet class from the Applet class.

Here’s an example of its use:

showStatus("MyApplet: Loading image file " + file);

Note

Please don’t put scrolling text in the status line. Browser users find such status line abuse highly annoying!

Displaying Documents in the Browser

Have you ever wanted an applet to display formatted HTML text? There’s an easy way to do it: Ask the browser to display the text for you.

With the AppletContext showDocument methods, an applet can tell the browser which URL to show and in which browser window.

Here are the two forms of showDocument:

public void showDocument(java.net.URL url)
public void showDocument(java.net.URL url, String targetWindow)

The one-argument form of showDocument simply tells the browser to display the document at the specified URL, without specifying the window to display the document in.

Terminology Note

In this discussion, frame refers not to a Swing JFrame, but to an HTML frame within a browser window.

The two-argument form of showDocument lets you specify which window or HTML frame to display the document in. The second argument can have the values listed below:

  • "_blank"Display the document in a new, nameless window.

  • "windowName"Display the document in a window named windowName. This window is created if necessary.

  • "_self"Display the document in the window and frame that contain the applet.

  • "_parent"Display the document in parent frame of the applet’s frame. If the applet frame has no parent frame, this acts the same as "_self".

  • "_top"Display the document in the top-level frame. If the applet’s frame is the top-level frame, this acts the same as "_self".

Run an applet[17] that lets you try every option of both forms of showDocument (Figure 18.7). The applet brings up a window that lets you type in a URL and choose any of the showDocument options (Figure 18.8). When you press Return or click the Show document button, the applet calls showDocument.

A screenshot of the Bring up URL window applet.

Figure 18.7. A screenshot of the Bring up URL window applet.

A screenshot of the ShowDocument applet.

Figure 18.8. A screenshot of the ShowDocument applet.

Below is the applet code that calls showDocument:[18]

  ...// In an Applet subclass:
  urlWindow = new URLWindow(getAppletContext());
  ...
class URLWindow extends Frame {
  ...
  public URLWindow(AppletContext appletContext) {
    ...
    this.appletContext = appletContext;
    ...
  }
  ...
  public boolean action(Event event, Object o) {
    ...
    String urlString = /* user-entered string */;
    URL url = null;
    try {
        url = new URL(urlString);
    } catch (MalformedURLException e) {
        ...// Inform the user and return...
    }
    if (url != null) {
      if (/* user doesn't want to specify the window */) {
          appletContext.showDocument(url);
      } else {
          appletContext.showDocument(url,
            /* user-specified window */ );
      }
    }
    ...

Sending Messages to Other Applets

Applets can find other applets and send messages to them, with the following security restrictions:

  • Many browsers require that the applets originate from the same server.

  • Many browsers further require that the applets originate from the same directory on the server (the same code base).

  • The Java API requires that the applets be running on the same page, in the same browser window.

Note

Some browsers let applets invoke methods on other applets—even applets on different pages in the same browser—as long as all of the applets come from the same code base. This method of interapplet communication isn’t supported by the Java API, so it’s possible that it will not be supported by all browsers.

An applet can find another applet either by looking it up by name (using the AppletContext getApplet method) or by finding all the applets on the page (using the AppletContext getApplets method). Both methods, if successful, give the caller one or more Applet objects. Once the caller finds an Applet object, the caller can invoke methods on the object.

Finding an Applet by Name: The getApplet Method

The getApplet method looks through all of the applets on the current page to see if one of them has the specified name. If so, getApplet returns the applet’s Applet object.

By default, an applet has no name. For an applet to have a name, one must be specified in the HTML code that adds the applet to a page. You can specify an applet’s name in two ways:

  • By specifying a NAME attribute within the applet’s <APPLET> tag. For example:

    <APPLET CODEBASE=example/ CODE=Sender.class
      WIDTH=450
      HEIGHT=200
      NAME="buddy" >
    ...
    </APPLET>
    
  • By specifying a NAME parameter with a <PARAM> tag. For example:

    <APPLET CODEBASE=example/ CODE=Receiver.class
      WIDTH=450
      HEIGHT=50>
    <PARAM NAME="name" value="old pal">
    ...
    </APPLET>
    

Browser Note

Although at least one browser enabled with Java technology conducts a case-sensitive search, the expected behavior is for the getApplet method to perform a case-insensitive search. For example, getApplet("old pal") and getApplet("OLD PAL") should both find an applet named “Old Pal”.

Two applets[19] illustrate lookup by name (Figures 18.9 and 18.10). The first, the Sender, looks up the second, the Receiver. When the Sender finds the Receiver, the Sender sends a message to the Receiver by invoking one of the Receiver’s methods (passing the Sender’s name as an argument). The Receiver reacts to this method call by changing its leftmost text string to “Received message from sender-name!”.

A screenshot of the Sender applet.

Figure 18.9. A screenshot of the Sender applet.

A screenshot of the Receiver applet.

Figure 18.10. A screenshot of the Receiver applet.

Try This

Click the Send message button of the first applet (the Sender). Some status information will appear in the Sender’s window, and the Receiver will confirm (with its own status string) that it received a message, After you’ve read the Receiver status string, press the Receiver’s Clear button to reset the Receiver. In the Sender’s text field labeled “Receiver name:,” type in buddy and press Return. Since “buddy” is the Sender’s own name, the Sender will find an applet named buddy but won’t send it a message, since it isn’t a Receiver instance.

The code the Sender program[20] uses to look up and communicate with the Receiver is listed below. Code that you can use without change in your own applet is in bold font:

Applet receiver = null;
String receiverName = nameField.getText(); // Get name
                                           // to search for.
receiver = getAppletContext().getApplet(receiverName);

The Sender goes on to make sure that the Receiver was found and that it’s an instance of the correct class (Receiver[21]). If all goes well, the Sender sends a message to the Receiver:

if (receiver != null) {
  // Use the instanceof operator to make sure the applet
  // we found is a Receiver object.
  if (!(receiver instanceof Receiver)) {
      status.appendText("Found applet named " +
                        receiverName + ", " +
                        "but it's not a Receiver object.
");
  } else {
      status.appendText("Found applet named " +
                        receiverName + ".
" +
                        " Sending message to it.
");
      // Cast the receiver to be a Receiver object
      // (instead of just an Applet object) so that the
      // compiler will let us call a Receiver method.
      ((Receiver)receiver).processRequestFrom(myName);
  }
} ...

From an applet’s point of view, its name is stored in a parameter named NAME. It can get the value of the parameter using the Applet getParameter method. For example, Sender gets its own name with the following code:

myName = getParameter("NAME");

For more information on using getParameter, see the Writing the Code to Support Parameters section (page 573).

The example applets in this section perform one-way communication—from the Sender to the Receiver. If you want your receiver to be able to send messages to the sender, then you just need to have the sender give a reference to itself (this) to the receiver. For example:

((Receiver)receiver).startCommunicating(this);

Finding All the Applets on a Page: The getApplets Method

The getApplets method returns a list (an Enumeration,[22] to be precise) of all the applets on the page. For security reasons, many browsers and applet viewers implement getApplets so that it returns only those applets that originated from the same host as the applet calling getApplets. Run an applet that simply lists all the applets it can find on this page (Figure 18.11).[23]

A screenshot of the GetApplets applet.

Figure 18.11. A screenshot of the GetApplets applet.

Below are the relevant parts of the method that calls getApplets:[24]

public void printApplets() {
  // Enumeration will contain all applets on this page
  // (including this one) that we can send messages to.
  Enumeration e = getAppletContext().getApplets();
  ...
  while (e.hasMoreElements()) {
    Applet applet = (Applet)e.nextElement();
    String info = ((Applet)applet).getAppletInfo();
    if (info != null) {
        textArea.appendText("- " + info + "
");
    } else {
        textArea.appendText("- " +
                           applet.getClass().getName() + "
");
    }
  }
  ...
}

Playing Sounds

The JApplet class in the Java Swing package (javax.swing) and the AudioClip[25] interface in the Java Applet package (java.applet) provide basic support for playing sounds. Currently, the Java API supports only one sound format: 8 bit, ν-law, 8000 Hz, one-channel, Sun “.au” files. You can create these on a Sun workstation using the audiotool application. You can convert files from other sound formats using an audio format conversion program.

Sound-Related Methods

Below are the sound-related Applet methods. The two-argument form of each method takes a base URL, which is usually returned by either getDocumentBase or getCodeBase, and the location of the sound file relative to the base URL:

  • getAudioClip(URL), getAudioClip(URL, String)Return an object that implements the AudioClip interface.

  • play(URL), play(URL, String)Play the AudioClip corresponding to the specified URL.

The AudioClip interface defines the following methods:

  • loopStarts playing the clip repeatedly.

  • playPlays the clip once.

  • stopStops the clip. Works with both looping and one-time sounds.

An Example

Run an applet called SoundExample[26] that illustrates a few things about sound (Figure 18.12). Note that, for instructional purposes, the applet adds up to 10 seconds to the load time for each sound. If the sounds were larger or the user’s connection slower than ours, these delays might be realistic.

A screenshot of the SoundExample applet.

Figure 18.12. A screenshot of the SoundExample applet.

The SoundExample applet provides an architecture for loading and playing multiple sounds in an applet. For this reason, it is more complex than necessary. Essentially, the sound loading and playing code boils down to this:

AudioClip onceClip, loopClip;
onceClip = applet.getAudioClip(getCodeBase(), "bark.au");
loopClip = applet.getAudioClip(getCodeBase(), "train.au");
onceClip.play();     // Play it once.
loopClip.loop();     // Start the sound loop.
loopClip.stop();     // Stop the sound loop.

Since there’s nothing more annoying than an applet that continues to make noise after you’ve left its page, the SoundExample applet stops playing the continuously looping sound when the user leaves the page and resumes playing it when the user comes back. It does this by implementing its stop and start methods as follows:

public void stop() {
  // If one-time sound were long, we'd stop it here, too.
  // looping is a boolean instance variable that's initially
  // false. It's set to true when the "Start sound loop" button
  // is clicked and to false when the "Stop sound loop" or
  // "Reload sounds" button is clicked.
  if (looping) {
    loopClip.stop();    // Stop the sound loop.
  }
}
public void start() {
  if (looping) {
    loopClip.loop();    // Restart the sound loop.
  }
}

The SoundExample applet features three classes:

  • A JApplet subclass, SoundExample,[27] that controls the applet’s execution.

  • A Hashtable subclass, SoundList,[28] that holds AudioClips. This is overkill for this applet, but if you were to write an applet that used lots of sound files, a class like this would be useful.

  • A Thread subclass, SoundLoader,[29] each instance of which loads an AudioClip in the background. During the applet’s initialization, the applet preloads each sound by creating a SoundLoader for it.

Preloading the sounds in a background thread (with SoundLoader) improves the perceived performance by reducing the amount of time the user has to wait to be able to interact with the applet. It does this by reducing the amount of time spent in the init method. If you simply called getAudioClip in the applet’s init method, it could take quite a while before getAudioClip returned, meaning that the applet couldn’t perform the other statements in its init method, and that the applet’s start wouldn’t get called. (For this SoundExample applet, a delay in calling the start method doesn’t matter.)

Another advantage of loading the sounds in a background thread is that it enables the applet to respond appropriately (and immediately) to user input that would normally cause a sound to play, even if that sound hasn’t been loaded yet. If you simply use the Applet play method, for example, then the first time the user does something to make the applet play a particular sound, the applet’s drawing and event handling are frozen while the sound is loaded. Instead, this applet detects that the sound hasn’t been loaded yet and responds appropriately.

This example is discussed in more detail in the Threads in Applets: Examples section (page 586).

Defining and Using Applet Parameters

Parameters are to applets what command-line arguments are to applications. They allow the user to customize the applet’s operation. By defining parameters, you can increase your applet’s flexibility, making your applet work in multiple situations without recoding and recompiling it.

The next few sections discuss parameters from the applet programmer’s point of view. To learn about the user view of parameters, see the Specifying Parameters section (page 575).

Deciding Which Parameters to Support

This section guides you through the four questions you should ask as you implement parameters:

What should the applet let the user configure?

What should the parameters be named?

What kind of value should each parameter take?

What should the default value of each parameter be?

It ends with a discussion of the parameters defined in a sample <APPLET> tag.

What Should the Applet Let the User Configure?

The parameters your applet should support depend on what your applet does and on how flexible you want it to be. Applets that display images might have parameters to specify the image locations. Similarly, applets that play sounds might have parameters to specify the sounds.

Besides parameters that specify resource locations (such as image and sound files), applets sometimes provide parameters for specifying details of the applet’s appearance or operation. For example, an animation applet might let the user specify the number of images shown per second. Or an applet might let the user change the strings the applet displays. Anything is possible.

What Should the Parameters Be Named?

Once you decide what parameters your applet will support, you need to figure out their names. Here are some typical parameter names:

  • SOURCE or SRCFor a data file such as an image file.

  • XXXSOURCE (for example, IMAGESOURCE)Used in applets that let the user specify more than one type of data file.

  • XXXSFor a parameter that takes a list of XXXs (where XXX might be IMAGE, again).

  • NAMEUsed only for an applet’s name. Applet names are used for interapplet communication, as described in the Sending Messages to Other Applets section (page 564).

Clarity of names is more important than keeping the name length short. Do not use names of <APPLET> tag attributes, which are documented in the Using the applet Tag section (page 595).

Note

Although this tutorial usually refers to parameter names using ALL UPPERCASE, parameter names are case-insensitive. For example, IMAGESOURCE and imageSource both refer to the same parameter. Parameter values, on the other hand, are case-sensitive unless you take steps to interpret them otherwise, such as by using the String toLowerCase method before interpreting the parameter’s value.

What Kind of Value Should Each Parameter Take?

Parameter values are all strings. Whether or not the user puts quotation marks around a parameter value, that value is passed to your applet as a string. However, your applet can interpret the string in many ways.

Applets typically interpret a parameter value as one of the following types:

  • A URL

  • An integer

  • A floating-point number

  • A boolean value—typically “true”/“false” or “yes”/“no”

  • A string—for example, the string to use as a window title

  • A list of any of the above

What Should the Default Value of Each Parameter Be?

Applets should attempt to provide useful default values for each parameter, so that the applet will execute even if the user doesn’t specify a parameter or specifies it incorrectly. For example, an animation applet should provide a reasonable setting for the number of images it displays per second. This way, if the user doesn’t specify the relevant parameter, the applet will still work well.

An Example: A Sample <APPLET> Tag

Here’s what a typical <APPLET> tag looks like.

<APPLET CODE=SampleApplet.class CODEBASE=example
  WIDTH=350 HEIGHT=60>
<PARAM NAME=windowClass VALUE=BorderWindow>
<PARAM NAME=windowTitle VALUE="BorderLayout">
<PARAM NAME=buttonText
  VALUE="Click here to see a BorderLayout in action">
</APPLET>

When the user doesn’t specify a value for a parameter, the applet uses a reasonable default value. For example, if the user doesn’t specify the window’s title, the applet uses the window’s type as the title.

The next section shows you how to get parameter values from the user.

Writing the Code to Support Parameters

Applets use the Applet getParameter method to get user-specified values for applet parameters. The getParameter method is defined as follows:

public String getParameter(String name)

Your applet might need to convert the string that getParameter returns into another form, such as an integer. The java.lang package provides classes such as Integer that you can use to help with converting strings to primitive types. Here’s an example of converting a parameter’s value into an integer:

int requestedWidth = 0;
...
String windowWidthString = getParameter("WINDOWWIDTH");
if (windowWidthString != null) {
  try {
      requestedWidth = Integer.parseInt(windowWidthString);
  } catch (NumberFormatException e) {
      // Use default width.
  }
}

Note that if the user doesn’t specify a value for the WINDOWWIDTH parameter, the above code uses a default value of 0, which the applet interprets as “use the window’s natural size.” It’s important that you supply default values wherever possible.

Besides using the getParameter method to get values of applet-specific parameters, you can also use getParameter to get the values of attributes of the applet’s <APPLET> tag. See the Using the applet Tag section (page 595) for a list of <APPLET> tag attributes.

Giving Information about Parameters

Now that you’ve provided all those nice parameters to the user, you need to help the user set the parameter values correctly. Of course, your applet’s documentation should describe each parameter and give the user examples and hints about setting them. Your job doesn’t stop there, though. You should also implement the getParameterInfo method so that it returns information about your applet’s parameters. Browsers can use this information to help the user set your applet’s parameter values.

Below is an example of implementing the getParameterInfo method:

public String[][] getParameterInfo() {
  String[][] info = {
    // Parameter Name  Kind of Value  Description
    {"imagesource",    "URL",         "a directory"},
    {"startup",        "URL",         "displayed at startup"},
    {"background",     "URL",         "displayed " +
                                             "as background"},
    {"startimage",     "int",         "start index"},
    {"endimage",       "int",         "end index"},
    {"namepattern",    "URL",         "used to generate " +
                                             "indexed names"},
    {"pause",          "int",         "milliseconds"},
    {"pauses",         "ints",        "milliseconds"},
    {"repeat",         "boolean",     "repeat or not"},
    {"positions",      "coordinates", "path"},
    {"soundsource",    "URL",         "audio directory"},
    {"soundtrack",     "URL",         "background music"},
    {"sounds",         "URLs",        "audio samples"},
  };
  return info;
}

As you can see, the getParameterInfo method must return an array of three-String arrays. In each three-String array, the first string is the parameter name. The second string gives the user a hint about what general kind of value the applet needs for the parameter. The third string describes the meaning of the parameter.

Using the APPLET Tag

This section tells you most of what you need to know to use the <APPLET> tag. It starts by showing you the tag’s simplest form. It then discusses some of the most common additions to that simple form: the <PARAM> tag, alternate HTML code and text, the CODEBASE attribute, and the ARCHIVE attribute. For a detailed description of the <APPLET> tag, refer to the Using the applet Tag section (page 595).

You should already have seen the simplest form of the <APPLET> tag:

<APPLET CODE=AppletSubclass.class WIDTH=anInt HEIGHT=anInt>
</APPLET>

This tag tells the browser to load the applet whose Applet subclass is named AppletSubclass, displaying it in an area of the specified width and height.

Specifying Parameters

Some applets let the user customize the applet’s configuration with parameters, as described in the Defining and Using Applet Parameters section (page 570). For example, AppletButton (an applet used throughout this tutorial to provide a button that brings up a window) allows the user to set the button’s text by specifying the value of a parameter named BUTTONTEXT.

The developer provides the value of a parameter using a <PARAM> tag. The <PARAM> tags should appear just after the <APPLET> tag for the applet they affect:

<APPLET CODE=AppletSubclass.class WIDTH=anInt HEIGHT=anInt>
<PARAM NAME=parameter1Name VALUE=aValue>
<PARAM NAME=parameter2Name VALUE=anotherValue>
</APPLET>

Here’s an example of the <PARAM> tag in use.

<APPLET CODE="Animator.class" WIDTH=460 HEIGHT=160>
<PARAM NAME="imageSource" VALUE="images/Beans">
<PARAM NAME="backgroundColor" VALUE="0xc0c0c0">
<PARAM NAME="endImage" VALUE=10>
<PARAM NAME="soundSource" VALUE="audio">
<PARAM NAME="soundtrack" VALUE="spacemusic.au">
<PARAM NAME="sounds"
  VALUE="1.au|2.au|3.au|4.au|5.au|6.au|7.au|8au|9.au|0.au">
<PARAM NAME="pause" VALUE=200>
...
</APPLET>

Specifying Alternate HTML Code and Text

Note the ellipsis points (“...”) in the previous HTML example. What did the example leave out? It omitted alternate HTML code-HTML code interpreted only by browsers that don’t understand the <APPLET> tag. Alternate HTML code is any text that appears between the <APPLET> and </APPLET> tags, after any <PARAM> tags. Browsers enabled with Java technology ignore alternate HTML code.

To specify alternate text to browsers enabled with Java technology and other browsers that understand the <APPLET> tag, use the ALT attribute. If the browser can’t display an applet for some reason, it can display the applet’s ALT text.

We use alternate HTML code throughout the online version of this tutorial to tell readers about the applets they’re missing. Often, the alternate HTML code includes one or more pictures of the applet. Here’s the complete HTML code for the Animator example shown previously:

<APPLET CODE="Animator.class" WIDTH=460 HEIGHT=160
  ALT="If you could run this applet, you'd see some animation">
<PARAM NAME="imageSource" VALUE="images/Beans">
<PARAM NAME="backgroundColor" VALUE="0xc0c0c0">
<PARAM NAME="endImage" VALUE=10>
<PARAM NAME="soundSource" VALUE="audio">
<PARAM NAME="soundtrack" VALUE="spacemusic.au">
<PARAM NAME="sounds"
  VALUE="1.au|2.au|3.au|4.au|5.au|6.au|7.au|8au|9.au|0.au">
<PARAM NAME="pause" VALUE=200>
Your browser is completely ignoring the &lt;APPLET&gt; tag!
</APPLET>

A browser that doesn’t understand the <APPLET> tag ignores everything in the previous HTML code except the line that starts with “Your”. A browser that does understand the <APPLET> tag ignores everything on that line. If the applet-savvy browser can’t run the applet, it might display the ALT text.

Specifying the Applet Directory

By default, a browser looks for an applet’s class and archive files in the same directory as the HTML file that has the <APPLET> tag. (If the applet’s class is in a package, then the browser uses the package name to construct a directory path underneath the HTML file’s directory.) Sometimes, however, it’s useful to put the applet’s files somewhere else. You can use the CODEBASE attribute to tell the browser in which directory the applet’s files are located:

<APPLET CODE=AppletSubclass.class CODEBASE=aURL
  WIDTH=anInt HEIGHT=anInt>
</APPLET>

If aURL is a relative URL, then it’s interpreted relative to the HTML document’s location. By making aURL an absolute URL, you can load an applet from just about anywhere—even from another HTTP server.

This book uses CODEBASE="someDirectory/" frequently, since we group the examples for each chapter in subdirectories. For example, here’s the <APPLET> tag that includes the Simple applet in The Life Cycle of an Applet section (page 547):

<APPLET CODE=Simple.class CODEBASE="example/"
  WIDTH=500 HEIGHT=20>
</APPLET>

Figure 18.13 shows the location of the class file, relative to the HTML file, when CODEBASE is set to "example/".

Location of the class file when CODEBASE is set to "example/".

Figure 18.13. Location of the class file when CODEBASE is set to "example/".

Figure 18.14 shows where the applet class can be if you specify an absolute URL for the value of CODEBASE.

Location of the class file when CODEBASE is set to an absolute URL.

Figure 18.14. Location of the class file when CODEBASE is set to an absolute URL.

Combining an Applet’s Files into a Single File

If your applet has more than one file, you should consider providing an archive file that bundles the applet’s files into a single file. Whether archive files make sense for your applet depends on several factors, including your applet’s size, performance considerations, and the environment you expect your users to have.

Archive files reduce your applet’s total download time. Much of the time saved comes from reducing the number of HTTP connections that the browser must make. Each HTTP connection can take several seconds to start. This means that for a multifile applet, connection time can dwarf transfer time. You can further reduce transfer time by compressing the files in your archive file.

If you specify one or more archive files, then the applet class loader looks for the archive files in the same directory that it would search for the applet class file. The applet class loader then looks for the applet’s class files in the archive files. If a file isn’t in the archive, then the applet class loader generally tries to load it in the browser just as it would if the archive file weren’t present.

The standard Java archive format, called JAR, was introduced in JDK 1.1 and is based on the ZIP file format. You specify JAR files using the ARCHIVE attribute of the <APPLET> tag. You can specify multiple archive files by separating them with commas:

<APPLET CODE="AppletSubclass.class" ARCHIVE="file1, file2"
  WIDTH=anInt HEIGHT=anInt>
</APPLET>

Unfortunately, not all browsers understand the same archive format or use the same HTML code to specify the applet archive. Watch this page for the latest information about browser support for archives. To learn how to create a JAR file, see the Creating a JAR File section (page 490).

Other <APPLET> Tag Attributes

This section didn’t discuss every attribute of the <APPLET> tag. Other attributes—which might seem familiar, since the <IMG> HTML tag uses them—include ALIGN, VSPACE, and HSPACE. The <APPLET> tag also allows you to load a serialized (saved) applet by specifying the OBJECT attribute instead of specifying a class file with CODE. Finally, you can name an applet using the NAME attribute. For a detailed description of the <APPLET> tag, see the Using the applet Tag section (page 595).

Practical Considerations When Writing Applets

The first two sections in this chapter discussed all of the applet-specific API. However, most applets rely on a lot of API that isn’t specific to applets. This section gives you hints about using the Java API, covering the areas that are affected by applets’ close relationships with browsers.

Security Restrictions

One of the main goals of the Java environment is to make browser users feel secure running any applet. To achieve this goal, we’ve started out conservatively, restricting capabilities perhaps more than necessary. As time passes, applets will probably get more and more abilities.

This section tells you about the current applet security restrictions, from the point of view of how they affect applet design. For more information on applet security, you should refer Frequently Asked Questions—Applet Security.[30]

Each applet viewer has a SecurityManager object that checks for applet security violations. When a SecurityManager detects a violation, it creates and throws a SecurityException object. Generally, the SecurityException constructor prints a warning message to the standard output. An applet can catch SecurityExceptions and react appropriately, such as by reassuring the user and by resorting to a “safer” (but less ideal) way of accomplishing the task.

Some applet viewers swallow some SecurityExceptions, so that the applet never gets the SecurityException. For example, the JDK Applet Viewer’s implementation of the AppletContext getApplet and getApplets methods simply catches and ignores any SecurityExceptions. The user can see an error message in the standard output, but at least the applet gets a valid result from the methods. This makes some sense, since getApplets should be able to return any valid applets it finds, even if it encounters invalid ones. (The Applet Viewer considers an applet valid if it’s loaded from the same host as the applet that’s calling getApplets.)

To learn about security managers and the kinds of security violations they can check for, see The Security Manager section (page 455).

Existing applet viewers (including Web browsers) impose the following restrictions:

  • Applets cannot load libraries or define native methods. Applets can use only their own Java code and the Java API the applet viewer provides. At a minimum, each applet viewer must provide access to the API defined in the java.* packages.

  • An applet cannot ordinarily read or write files on the host that is executing it. The JDK Applet Viewer actually permits some user-specified exceptions to this rule, but older browsers generally do not. Applets in any applet viewer can read files specified with full URLs, instead of by a filename. A workaround for not being able to write files is to have the applet forward data to an application on the host the applet came from. This application can write the data files on its own host. See the Working with a Server-Side Application section (page 589) for more examples.

  • An applet cannot make network connections except to the host that it came from. The workaround for this restriction is to have the applet work with an application on the host it came from. The application can make its own connections anywhere on the network. See the Using a Server to Work Around Security Restrictions section (page 591) for an example.

  • An applet cannot start any program on the host that is executing it. Again, an applet can work with a server-side application instead.

  • An applet cannot read certain system properties. See the Getting System Properties section (page 583) for more information.

  • Windows that an applet brings up look different than windows that an application brings up. You can identify the Applet window by the name “Java Applet Window,” which is displayed at the bottom of the window. The application window would not have any name at its bottom. This helps the user distinguish applet windows from those of trusted applications.

    Figures 18.15 and 18.16 show a window brought up by a program that can run either as an applet or as an application. Figure 18.15 shows what the window looks like when the program is run as an application on the Microsoft Windows platform. Figure 18.16 shows the window when the program runs as an applet on the Windows platform within the Mozilla browser.

    A program running as an application.

    Figure 18.15. A program running as an application.

    Same program running as an applet.

    Figure 18.16. Same program running as an applet.

As you can see, the applet window has a label informing the user that it is running as an applet.

Creating a User Interface

Most applets have a graphical user interface (GUI). This is a natural consequence of the fact that each applet appears within a browser window. Because the JApplet class is a subclass of the Applet class, which is a subclass of the AWT Panel class and thus participates in the AWT event and drawing model, creating an applet’s GUI is just as easy as creating an application’s GUI. It’s easier, actually, since the applet’s window (the browser window) already exists.

In addition to its graphical UI, an applet can use several other UI types, depending on the kind of information it needs to give or get. Some applets play sounds, either to give the user feedback or to provide ambiance. Applets can get configuration information from the user through parameters that the applet defines. To give text information to the user, an applet can use its GUI, display a short status string (for text that’s not crucial), or display to the standard output or standard error stream (for debugging purposes).

For information about sound, parameters, and status strings, see the Taking Advantage of the Applet API section (page 559).

Creating a GUI

This section discusses the few issues that are particular to applet GUIs. Some of the information in this section might not make sense until you’ve read the Creating a GUI with JFC/Swing and, in particular, the How to Make Applets section.[31] That trail discusses all the GUI concepts referred to in this section:

  • Applets appear in preexisting browser windows. This has two implications. First, unlike GUI-based applications, applets don’t have to create a window in which to display themselves. They can, if they have a good reason, but they often just display themselves within the browser window. Second, depending on the browser implementation, your applet’s components might not be shown unless your applet calls validate after adding components to itself. Fortunately, calling validate can’t hurt.

  • The applet background color might not match the page color. By default, applets have a white background color. HTML pages, however, can have other background colors and can use background patterns. If the applet designer and page designer aren’t careful, the applet’s different background color can cause it to stick out on the page or cause noticeable flashing when the applet is drawn. One solution is to define an applet parameter that specifies the applet’s background color. The JApplet class can use JComponent’s setBackground method to set the applet’s background to the color specified in the Web page. Using the background color parameter, the page designer can choose an applet color that works well with the page colors. You’ve learned about parameters in the Defining and Using Applet Parameters section (page 570).

  • Each applet has a user-specified, predetermined size. The <APPLET> tag requires that the applet’s width and height be specified. The Web designer can set an applet’s size by pixels or by indicating a percentage of the browser window. Note that even if the amount of space is ideal for one platform, the platform-specific parts of the applet (such as buttons) might require a different amount of space on another platform. You can compensate by recommending that pages that include your applet specify a little more space than might be necessary, and by using flexible layouts, such as the GridBagLayout and BorderLayout classes, that adapt well to extra space.

  • Applets load images using the Applet getImage methods. The Applet class provides a convenient form of getImage that lets you specify a base URL as one argument, followed by a second argument that specifies the image file location, relative to the base URL. The Applet getCodeBase and getDocumentBase methods provide the base URLs that most applets use. Images that an applet always needs, or needs to rely on as a backup, are usually specified relative to where the applet’s code was loaded from (the code base). Images that are specified by the applet user (often with parameters in the HTML file) are usually relative to the page that includes the applet (the document base).

  • Applet classes (and often the data files they use) are loaded over the network, which can be slow. Applets can do several things to decrease the perceived startup time. The Applet subclass can be a small one that immediately displays a status message. If some of the applet’s classes or data aren’t used right away, the applet can preload the classes or data in a background thread.

    For example, the AppletButton[32] class start method launches a thread that gets the Class[33] object for the window the button brings up. The applet’s main purpose in doing so is to make sure the class name that the user specified is valid. An added benefit is that getting the Class object forces the class file to be loaded before the class is instantiated. When the user requests that the window be created, the applet instantiates the window class much quicker than if the applet still had to load the window class file.

Displaying Diagnostics to the Standard Output and Error Streams

Displaying diagnostics to the standard output can be an invaluable tool when you’re debugging an applet. Another time you’ll see messages at the standard output is when an uncaught exception occurs in an applet. Applets also have the option of using the standard error stream.

Where exactly the standard output and error are displayed varies, depending on how the applet’s viewer is implemented, what platform it’s running on, and (sometimes) how you launch the browser or applet viewer. When you launch the Applet Viewer from a UNIX shell window, for example, strings displayed to the standard output and error appear in that shell window, unless you redirect the output. When you launch the Applet Viewer from an X Windows menu, the standard output and error go to the console window.

Applets display to the standard output stream using System.out.print(String) and System.out.println(String). Displaying to the standard error stream is similar; just specify System.err instead of System.out. Here’s an example of displaying to the standard output:

// Where instance variables are declared:
boolean DEBUG = true;
...
// Later, when we want to print some status:
if (DEBUG) {
  System.out.println("Called someMethod(" + x + "," + y + ")");
}

Note

Displaying to the standard output and error streams is relatively slow. If you have a timing-related problem, printing messages to either of these streams might not be helpful.

You should be sure to disable all debugging output before you release your applet.

Getting System Properties

To find out about the current working environment, applets can read system properties. System properties are key/value pairs that contain information such as the operating system that the applet is running under. System properties are covered in detail in the Properties section (page 443).

Applets can read some, but not all, system properties.

System Properties That Applets Can Read

Applets can read the system properties listed in Table 18.1.

Table 18.1. Valid System Properties

Key

Meaning

"file.separator"

File separator (for example, “/”)

"java.class.version"

Java class version number

"java.vendor"

Java vendor-specific string

"java.vendor.url"

Java vendor URL

"java.version"

Java version number

"line.separator"

Line separator

"os.arch"

Operating system architecture

"os.name"

Operating system name

"path.separator"

Path separator (for example, “:”)

To read a system property from within an applet, the applet uses the System class method getProperty. For example:

String newline = System.getProperty("line.separator");

Run an applet[34] which reads all of the properties available to all applets (Figure 18.17).

A screenshot of the GetOpenProperties applet.

Figure 18.17. A screenshot of the GetOpenProperties applet.

You can find the source code in GetOpenProperties.java.[35]

Forbidden System Properties

For security reasons, no existing browsers or applet viewers let applets read the system properties listed in Table 18.2.

Table 18.2. Forbidden System Properties

Key

Meaning

"java.class.path"

Java classpath

"java.home"

Java installation directory

"user.dir"

User’s current working directory

"user.home"

User home directory

"user.name"

User account name

Threads in Applets

Note

This section assumes that you know what a thread is. If you don’t, please read the Processes and Threads section (page 369) before reading this section.

Every applet can run in multiple threads. The applet’s GUI is created on the event-dispatching thread. The threads that the major milestone methods—init, start, stop, and destroy—are called from depends on the application that’s running the applet. But no application ever calls them from the event-handling thread.

Many browsers allocate a thread for each applet on a page, using that thread for all calls to the applet’s major milestone methods. Some browsers allocate a thread group for each applet, so that it’s easy to kill all the threads that belong to a particular applet. In any case, you’re guaranteed that every thread created by any of an applet’s major milestone methods belongs to the same thread group.

Run a PrintThread applet[36] (Figure 18.18). PrintThread is a modified version of SimpleApplet that prints the thread and thread group that its init, start, stop, destroy, and update methods are called from.[37]

A screenshot of the PrintThread applet.

Figure 18.18. A screenshot of the PrintThread applet.

As usual, to see the output for the methods such as destroy that are called during unloading, you need to look at the standard output. For standard output for an applet run in a browser, open the Java Console from the browser’s Tools menu. See the Displaying Diagnostics to the Standard Output and Error Streams section (page 583) for information about the standard output stream.

So why would an applet need to create and use its own threads? Imagine an applet that performs some time-consuming initialization—loading images, for example—in its init method. The thread that invokes init cannot do anything else until init returns. In some browsers, this might mean that the browser can’t display the applet or anything after it until the applet has finished initializing itself. So if the applet is at the top of the page, for example, then nothing would appear on the page until the applet has finished initializing itself.

Even in browsers that create a separate thread for each applet, it makes sense to put any time-consuming tasks into an applet-created thread, so that the applet can perform other tasks while it waits for the time-consuming ones to be completed.

Rule of Thumb

If an applet performs a time-consuming task, it should create and use its own thread to perform that task.

Applets typically perform two kinds of time-consuming tasks: tasks that they perform once and tasks that they perform repeatedly. The next section gives an example of both.

Threads in Applets: Examples

This section discusses two examples of using threads in applets. The first applet, AnimatorApplet, shows how to use a thread to perform repeated tasks. The second applet this page discusses, SoundExample, shows how to use threads for one-time initialization tasks. SoundExample is featured in the Playing Sounds section (page 568).

This section does not explain basic thread code. To learn about the Java implementation of threads, refer to the Defining and Starting a Thread section (page 371).

Using a Thread to Perform Repeated Tasks

An applet that performs the same task over and over again typically should have a thread with a while (or do…while) loop that performs the task. A typical example is an applet that performs timed animation, such as a movie player or a game. Animation applets need a thread that requests repaints at regular intervals. Another example is an applet that reads data supplied by a server-side application. (See the Using a Server to Work Around Security Restrictions section, page 591, for such an example.)

Applets typically create threads for repetitive tasks in the applet start method. Creating the thread there makes it easy for the applet to stop the thread when the user leaves the page. All you need to do is implement the stop method so that it stops the applet’s thread. When the user returns to the applet’s page, the start method is called again, and the applet can again create a thread to perform the repetitive task.

Below is AnimatorApplet’s implementation of the start and stop methods:

public void start() {
  if (frozen) {
      // Do nothing. The user has requested that we
      // stop changing the image.
  } else {
      // Start animating!
      if (animatorThread == null) {
        animatorThread = new Thread(this);
      }
      animatorThread.start();
  }
}

public void stop() {
  animatorThread = null;
}

The this in new Thread(this) indicates that the applet provides the body of the thread. It does so by implementing the java.lang.Runnable interface, which requires the applet to provide a run method that forms the body of the thread. We’ll discuss AnimatorApplet’s run method more a little later.

Notice that nowhere in the AnimatorApplet class is the Thread stop method called. This is because calling the Thread stop method is like clubbing the thread over the head. It’s a drastic way to get the thread to stop what it’s doing. Instead, you can write the thread’s run method in such a way that the thread will gracefully exit when you tap it on the shoulder. This shoulder tap comes in the form of setting to null an instance variable of type Thread.

In AnimatorApplet, this instance variable is called animatorThread. The start method sets it to refer to the newly created Thread object. When the applet needs to kill the thread, it sets animatorThread to null. This kills the thread not by making it be garbage collected—it can’t be garbage collected while it’s runnable—but because at the top of its loop, the thread checks animatorThread, continuing or exiting depending on the value of animatorThread. Here’s the relevant code:

public void run() {
  ...
  while (Thread.currentThread() == animatorThread) {
    ...// Display a frame of animation and then sleep.
  }
}

If animatorThread refers to the same thread as the currently executing thread, the thread continues executing. If, on the other hand, animatorThread is null, the thread exits. If animatorThread refers to another thread, then a race condition has occurred: start has been called so soon after stop (or this thread has taken such a long time in its loop) that start has created another thread before this thread reached the top of its while loop. Whatever the cause of the race condition, this thread should exit.

For more information about animation applets, see Threads in Applets, a section in Creating a GUI with JFC/Swing.

Using a Thread to Perform One-Time Initialization

If your applet needs to perform some initialization task that can take a while, you should consider ways of performing the initialization in a thread. For example, anything that requires making a network connection should generally be done in a background thread. Fortunately, GIF, PNG, and JPEG image loading is automatically done in the background using threads that you don’t need to worry about.

Sound loading, unfortunately, is not guaranteed to be done in the background. In current implementations, the Applet getAudioClip methods don’t return until they’ve loaded all the audio data. As a result, if you want to preload sounds, you might want to create one or more threads to do so.

Using a thread to perform a one-time initialization task for an applet is a variation of the classic producer/consumer scenario. The thread that performs the task is the producer, and the applet is the consumer. The Synchronization section (page 377) discusses how to use Java threads in a producer/consumer scenario.

SoundExample adheres closely to the model presented in Synchronizing Threads. Like the Synchronizing Threads example, SoundExample features three classes:[38]

  • The producer: SoundLoader, a Thread subclass.

  • The consumer: SoundExample, an Applet subclass. Unlike the Synchronizing Threads consumer example, SoundExample is not a Thread; it doesn’t even implement the Runnable interface. However, the SoundExample instance methods are executed by at least two threads, depending on the application that executes the SoundExample applet.

  • The storage object: SoundList, a Hashtable subclass. Unlike CubbyHole in the Synchronizing Threads example, SoundList can return null values if the sound data hasn’t been stored yet. This makes sense for this applet because it needs to be able to react immediately to a user request to play the sound, even if the sound hasn’t been loaded yet.

For more information on SoundExample, refer to the Playing Sounds section (page 568).

Working with a Server-Side Application

Applets, like other Java programs, can use the API defined in the java.net package to communicate across the network. The only difference is that, for security reasons, the only host an applet can communicate with is the host it was delivered from.

Note

Depending on the networking environment an applet is loaded into, and depending on the browser that runs the applet, an applet might not be able to communicate with its originating host. For example, browsers running on hosts inside firewalls often cannot get much information about the world outside the firewall. As a result, some browsers might not allow applet communication to hosts outside the firewall.

It’s easy to find out which host an applet came from. Just use the Applet getCodeBase method and the java.net.URL getHost method, like this:

String host = getCodeBase().getHost();

Once you have the right host name, you can use all the networking code that is documented in the Custom Networking trail in the online tutorial.[39]

Note

Not all browsers support all networking code flawlessly. For example, one widely used browser compatible with Java technology doesn’t support posting to a URL.

A Simple Network Client Applet

This section talks about the client to be an applet.[40] The client has been written not only to communicate with the host the applet came from, but also to have a graphical UI, and to have a loop so that it can get as many quotes as you like. You can run the applet by including it in a page with the following HTML code:

<APPLET CODE=QuoteClientApplet.class WIDTH=500 HEIGHT=100>
</APPLET>

The quoteApplet.html page[41] contains the above HTML code. By saving this page to a file on your local HTTP server, you can use it to communicate with the server-side application that will be running on the HTTP server. You must also save the compiled form of the applet to the same directory.

Before the applet can get quotes, you need to run the server on the host that the applet came from. You then need to note the number of the port that the server is listening on. After you enter this port number into the applet, it will hook up with the server and you’ll be able to get one-line quotations. Below are detailed instructions, followed by pictures of the server and the applet in action:

  1. Compile QuoteServer.java[42] and QuoteServerThread.java.[43] A text file (one-liners.txt[44]) should be in the same directory as the resulting class files.

  2. On the computer that serves the applet class file (through HTTP), invoke the interpreter on the QuoteServer class. For example, if you view the applet’s page with the URL http://mymachine/quoteApplet.html, then you need to run the server on the host named mymachine.

  3. Record the port number that the quote server displays.

  4. Enter this number into the applet’s text field.

  5. Press the Send button to request a quote from the server. You should see a quote appear in the text area.

Figure 18.19 shows a picture of the applet in action.

A screenshot of the QuoteServer applet.

Figure 18.19. A screenshot of the QuoteServer applet.

Using a Server to Work Around Security Restrictions

As the What Applets Can and Can’t Do section (page 558) explains, applets are subject to many security restrictions. For example, they can’t perform file I/O, they can’t make network connections except to their original host, and they can’t start programs.

One way of working around these restrictions is to use a server application that executes on the applet’s host. The server won’t be able to get around every applet restriction, but it can make more things possible. For example, a server probably can’t save files on the host the applet’s running on, but it will be able to save files on the host the applet originated from.

This section features an example of a server that allows two applets to communicate with each other. The applets don’t have to be running on the same page, in the same browser, or on the same computer. As long as the applets originate from the same computer, they can communicate through the server that’s running on that originating computer. The example uses sockets, which are documented in All About Sockets.[45]

Here are the source files:

  • TalkClientApplet.java[46]The source file for the client applet. After you compile it, you can run it by including it in an HTML page with this tag:

    <APPLET CODE=TalkClientApplet.class WIDTH=550 HEIGHT=200>
    </APPLET>
    

    The talk.html page[47] includes the above HTML code. After saving this page to a file on your local HTTP server, you can use it to communicate with the talk server.

  • TalkServer.java[48] and TalkServerThread.java[49]The source files for the server applet. After compiling both files, you can run the server on the applets’ originating host by invoking the interpreter on the TalkServer class.

The instructions for running the server are just like those for the previous example (see the A Simple Network Client Applet section, page 590). Run the server on the applets’ originating host, recording the port number that the applets should rendezvous on. Then initialize both applets (which can be running on different machines) to talk to the server port number. After this initialization is complete, type a string into each applet’s text field. Then press the Return key to send the message to the other applet.

Here’s the server in action:

www%  java TalkServer
TalkServer listening on rendezvous port: 36567

Figures 18.20 and 18.21 show pictures of the applets in action.

Sample talk output—machine #1.

Figure 18.20. Sample talk output—machine #1.

Sample talk output—machine #2.

Figure 18.21. Sample talk output—machine #2.

Finishing an Applet

Before You Ship That Applet

Stop! Before you let the whole world know about your applet, make sure the answer to all of the following questions is yes:

1.

Have you removed or disabled debugging output?

Debugging output (generally created with System.out.println), while useful to you, is generally confusing or annoying to users. If you need to give textual feedback to the user, try to do it inside the applet’s display area or in the status area at the bottom of the window. Information on using the status area is in the Displaying Short Status Strings section (page 561).

2.

Does the applet stop running when it’s offscreen?

Most applets should not use CPU resources when the browser is iconified or is displaying a page that doesn’t contain the applet. If your applet code doesn’t launch any threads explicitly, then you’re OK.

If your applet code launches any threads, then unless you have a really good excuse not to, you should implement the stop method so that it stops and destroys (by setting to null) the threads you launched. For an example of implementing the stop method, see the Threads in Applets: Examples section (page 586).

3.

If the applet does something that might get annoying—play sounds or animation, for example—does it give the user a way of stopping the annoying behavior?

Be kind to your users. Give them a way to stop the applet in its tracks, without leaving the page. In an applet that otherwise doesn’t respond to mouse clicks, you can do this by implementing the mouseDown method so that a mouse click suspends or resumes the annoying thread. For example:

boolean frozen = false; // an instance variable

public boolean mouseDown(Event e, int x, int y) {
  if (frozen) {
      frozen = false;
      start();
  } else {
      frozen = true;
      stop();
  }
  return true;
}

The Perfectly Finished Applet

The previous section lists some of the ways you can avoid making your applet’s users want to throttle you. This section tells you about some other ways that you can make dealing with your applet as pleasant as possible:

  • Make your applet as flexible as possible.

    You can often define parameters that let your applet be used in a variety of situations without any rewriting. See the Defining and Using Applet Parameters section (page 570) for more information.

  • Make your applet accessible.

    You can design your applet so that it is accessible to all. See the Swing chapter in the How to Support Assistive Technologies[50] section of the tutorial for more information.

  • Implement the getParameterInfo method.

    Implementing this method now might make your applet easier to customize in the future. Currently, no browsers use this method. Soon, however, we expect browsers to use this method to help generate a GUI that allows the user to interactively set parameter values. See the Giving Information about Parameters section (page 573) for information on implementing getParameterInfo.

  • Implement the getAppletInfo method.

    This method returns a short, informative string describing an applet. Although no browsers currently use this method, we expect them to in the future. Here’s an example of implementing getAppletInfo:

    public String getAppletInfo() {
      return "GetApplets by Kathy Walrath";
    }
    

Deploying Applets

This section explains to HTML authors how and when to use the applet, object, and embed tags to add Java applets to Web pages, and provides guidelines for deploying applets on the Internet and Intranets and for use with different browsers.

General Deployment Considerations

How you deploy an applet depends on whether users access the Web page through the Internet or an Intranet, and the type of browser they use. Note this information about your users, then follow the general guidelines below.

Deploying Applets on the Internet versus an Intranet

When deploying applets:

  • Use the applet tag if the Web page is accessed through the Internet or if it is accessed through an Intranet in which people use different browsers.

  • Use the object or embed tag if the Web page is accessed through an Intranet and you know which browser people use.

Deploying Applets for Specific Browsers

When deploying applets:

  • For Internet Explorer only, use the object tag.

  • For the Mozilla family of browsers only, use the embed tag.

If you must deploy an applet in a mixed-browser environment, follow the guidelines in the Deploying Applets in a Mixed-Browser Environment section (page 598).

Using the applet Tag

You use the applet tag to deploy applets to a multi-browser environment.

For complete details on the applet tag, read the W3 HTML specification.[51]

Note

The HTML specification states that the applet tag is deprecated and that you should use the object tag instead. However, the specification is vague about how browsers should implement the object tag to support Java applets, and browser support is currently inconsistent. It is therefore recommended that you continue to use the applet tag as a consistent way to deploy Java applets across browsers on all platforms.

Following is an example of the applet tag:

<applet code=Applet1.class width="200" height="200">
Your browser does not support the applet tag.
</applet>

For both Internet Explorer and the Mozilla family of browsers, if Java Plug-in is installed (version 1.3.1_01a or later) then the latest installed version of Java Plug-in is invoked to run the applet.

Note

You cannot use the applet tag to automatically download a JRE if one is not installed locally.

Using the object Tag

You use the object tag to deploy applets that are to be used only with Internet Explorer.

For complete details on the object tag, read the W3 HTML specification.

Following is an example of the object tag:

<OBJECT
  classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
  width="200" height="200">
  <PARAM name="code" value="Applet1.class">
</OBJECT>

The classid Attribute

The classid attribute identifies which version of Java Plug-in to use.

The example shown below is the most commonly used form of the classid attribute. This example instructs Internet Explorer to use the latest installed version of Java Plug-in:

classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"

Following is an alternative form of the classid attribute:

classid="clsid:CAFEEFAC-xxxx-yyyy-zzzz-ABCDEFFEDCBA"

In this form, “xxxx”, “yyyy”, and “zzzz” are four-digit numbers that identify the specific version of Java Plug-in to be used.

For example, to use Java Plug-in version 1.6.0, you specify:

classid="clsid:CAFEEFAC-0016-0000-0000-ABCDEFFEDCBA"

The codebase Attribute

You use the optional codebase attribute to specify the location to download JRE from in case it is not installed on the system.

The codebase attribute has two forms:

  • codebase=<URL>With this form, if the JRE specified by the classid attribute is not installed locally, then the user is prompted to download the JRE from the URL specified.

  • codebase=<URL>#Version=major,minor,micro,updateWith this form, Java Plug-in compares the classid of the locally installed JRE with the required version of JRE, and if the required version is higher, prompts the user to download and install the newer version of the JRE.

Following is an example of how to use the codebase attribute to set up automatic downloads from the Sun Java Web site:

<object
  classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
  width="200" height="200"
  codebase="http://java.sun.com/update/1.6.0/
    jinstall-6-windows-i586.cab#Version=6,0,0,99">
  <param name="code" value="Applet1.class">
</object>

Note

In this example, the codebase=http://java.sun.com … line is broken for readability. In the actual HTML file it would be one long line.

Sun has packaged each version of the JRE installer in Microsoft cabinet (.cab) file format. You can view a list of these releases and the corresponding .cab file names.[52]

Using the embed Tag

You use the embed tag to deploy applets that are to be used only with the Mozilla family of browsers.

Following is an example of the embed tag:

<embed code="Applet1.class"
  width="200" height="200"
  type="application/x-java-applet;version=1.6.0"
  pluginspage="http://java.sun.com/javase/downloads"/>

The type attribute can have one of two forms:

  • type="application/x-java-applet;version=1.6.0"With this form, the highest installed JRE that supports the MIME type

    application/x-java-applet;version=1.6.0
    

    is invoked to run the applet. If a JRE with a version number equal to or greater than the version number specified is installed locally, then that JRE is invoked. Otherwise the user is directed to the URL specified as the value of the pluginspage attribute and is prompted to download and install the required JRE.

  • type="application/x-java-applet;jpi-version=1.6.0_01With this form, a JRE with the exact version given by the the value of jpi-version (in this example, 1.6.0_01) is invoked to run the applet. Otherwise the user is directed to the URL specified as the value of the pluginspage attribute and is prompted to download and install the required JRE.

Deploying Applets in a Mixed-Browser Environment

You can deploy applets for users of both Internet Explorer and the Mozilla family of browsers in one of two ways:

  • Through pure HTML

  • Through JavaScript

Using Pure HTML

When using a pure HTML approach to deploy applets in a mixed-browser environment, note the following:

  • Internet Explorer

    • Recognizes the object tag

    • Ignores the contents of the comment tag

  • Mozilla browsers

    • Ignore an object tag with the classid attribute

    • Interpret the contents of the comment tag

Consider the following example code from an HTML page:

<object classid="clsid:CAFEEFAC-0016-0000-0000-ABCDEFFEDCBA"
  <param name="code" value="Applet1.class">
    <comment>
      <embed code="Applet1.class"
             type="application/x-java-applet;jpi-version=1.6">
        <noembed>
          No Java Support.
        </noembed>
      </embed>
    </comment>
</object>

Using JavaScript

Instead of using the pure HTML approach described above, you can use JavaScript to deploy applets in a mixed-browser environment.

Through JavaScript, you:

  1. Detect the user’s browser through the appName variable.

  2. Use the document.write() method to write a tag based on the value of the appName variable:

    1. If the browser name equals “Netscape”, write the embed tag.

    2. If the browser name equals “Microsoft Internet Explorer”, write the object tag.

In the following example, the document.write() method outputs either an embed or object tag for each user “on the fly”:

<html>
<script language="Javascript">

  var _app = navigator.appName;

  if (_app == 'Netscape') {
    document.write('<embed code="Applet1.class"',
      'width="200"',
      'height="200"',
      'type="application/x-java-applet;version=1.6">'),
    }
  else if (_app == 'Microsoft Internet Explorer') {
    document.write('<OBJECT ',
      'classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"',
      'width="200"',
      'height="200">',
      '<PARAM name="code" value="Applet1.class">',
      '</OBJECT>'),
    }
  else {
    document.write('<p>Sorry, unsupported browser.</p>'),
    }

</script>
</html>

You can use the HTML Converter tool[53] to help with generating object and embed tags for mixed environments.

Solving Common Applet Problems

This section covers some common problems that you might encounter when writing Java applets. After each problem there is a list of possible solutions.

Problem: Applet Viewer says there is no <APPLET> tag on my HTML page, but it really is there.

  • Check whether you have a closing applet tag: </APPLET>

Problem: I recompiled my applet, but my applet viewing application would not show the new version even though I told it to reload it.

  • In many applet viewers (including browsers), reloading is not reliable. This is why we recommend that you simply use the JDK Applet Viewer, invoking it anew every time you change the applet.

  • If you get an old version of the applet, no matter what you do, make sure that you don’t have an old copy of the applet in a directory in your CLASSPATH. See the Managing Source and Class Files section (page 191) for information about the CLASSPATH environment variable.

Problem: The background color of my applet causes the applet not to match or flicker when it is drawn on a page of a different color.

  • You need to set the background color of the applet so that it works well with the page color. See the Creating a GUI section (page 581) for details.

Problem: The Applet getImage method doesn’t work.

  • Make sure you’re calling getImage from the init method or a method that’s called after init. The getImage method does not work when it is called from a constructor.

Problem: Now that I have copied my applet’s class file onto my HTTP server, the applet doesn’t work.

  • Does your applet define more than one class? If so, make sure that the class file (ClassName.class) for each class is on the HTTP server. Even if all the classes are defined in one source file, the compiler produces one class file per class.

  • Did you copy all the data files for your applet—image and sound files, for example—to the server?

  • Make sure all the applet’s class and data files can be read by everyone.

  • Make sure the applet’s class and data files weren’t garbled during the transfer. One common source of trouble is using the ASCII mode of FTP (rather than the BINARY mode) to transfer files.

Problem: Applet is not loaded in my Web page. I see the error “java.lang.UnsupportedClassVersionError: Bad version number in .class file” in my Java Console.

  • The problem is that the source for the applet is compiled with a newer version of Java than the one installed on your system. Which JRE version are you using? If it is not the latest version, make sure you install the latest Java SE Runtime Environment (JRE).[54]

Tip for Deployers

You can compile your applets with JDK 6 using compile time options as source –1.2 and target –1.2, so that you can run them with the older versions of JRE.

Questions and Exercises: Java Applets

Questions

1.

Which classes can an applet extend?

2.

How do you cause the applet GUI in the browser to be refreshed when data in it may have changed?

3.

What do you use the start() method for?

4.

True or false: An applet can make network connections to any host on the Internet.

5.

How do you get the value of a parameter specified in the APPLET tag from within the applet’s code?

6.

True or false: An applet can run multiple threads.

7.

Match the following tag names with the descriptions in the following lists:

  1. EMBED tag

  2. APPLET tag

  3. OBJECT tag

  1. Use to deploy applets to a multi-browser environment.

  2. Use to deploy applets that are to be used only with the Mozilla family of browsers.

  3. Use to deploy applets that are to be used only with Internet Explorer.

Exercises

1.

For an applet using the Exercise class, write the Applet tag that sets the ButtonName parameter to Save.

2.

Write the method to display an applet in the browser so that the contents are contained in a rectangle around the phrase “Exercise Applet.” Have the applet be one pixel less than the size specified on the Web page and have the phrase start at the coordinates 5, 15.

Answers

You can find answers to these Questions and Exercises at:

tutorial/deployment/applet/QandE/answers.html


[1] docs/technotes/guides/plugin/developer_guide/contents.html

[2] tutorial/deployment/applet/examples/helloWorld.jar

[3] tutorial/deployment/applet/examples/HelloWorld.java

[4] tutorial/deployment/applet/SwingUI.java

[5] tutorial/deployment/applet/ApptoAppl.java

[6] tutorial/uiswing/components/rootpane.html

[7] tutorial/deployment/applet/examples/simple.jar

[8] tutorial/deployment/applet/examples/Simple.java

[9] docs/api/javax/swing/JApplet.html

[10] tutorial/deployment/applet/examples/SimpleClick.java

[11] tutorial/deployment/applet/examples/simpleClick.jar

[12] tutorial/uiswing/index.html

[13] tutorial/deployment/applet/examples/ScrollingSimple.java

[14] tutorial/uiswing/layout/index.html

[15] tutorial/deployment/applet/examples/scrollingSimple.jar

[16] docs/api/java/applet/Applet.html

[17] tutorial/deployment/applet/examples/showDocument.jar

[18] tutorial/deployment/applet/examples/ShowDocument.java

[19] tutorial/deployment/applet/examples/sender.jar

[20] tutorial/deployment/applet/examples/Sender.java

[21] tutorial/deployment/applet/examples/Receiver.java

[22] docs/api/java/util/Enumeration.html

[23] tutorial/deployment/applet/examples/getApplets.java

[24] tutorial/deployment/applet/examples/GetApplets.java

[25] docs/api/java/applet/AudioClip.html

[26] tutorial/deployment/applet/examples/sound.jar

[27] tutorial/deployment/applet/examples/SoundExample.java

[28] tutorial/deployment/applet/examples/SoundList.java

[29] tutorial/deployment/applet/examples/SoundLoader.java

[31] tutorial/uiswing/components/applet.html

[32] tutorial/uiswing/layout/example-swing/AppletButton.java

[33] docs/api/java/lang/Class.html

[34] tutorial/deployment/applet/examples/properties.jar

[35] tutorial/deployment/applet/examples/GetOpenProperties.java

[36] tutorial/deployment/applet/examples/threads.jar

[37] tutorial/deployment/applet/examples/PrintThread.java

[38] Refer to footnotes on page 570.

[39] tutorial/networking/index.html

[40] tutorial/deployment/applet/examples/QuoteClientApplet.java

[41] tutorial/deployment/applet/examples/quoteApplet.html

[42] tutorial/deployment/applet/examples/QuoteServer.java

[43] tutorial/deployment/applet/examples/QuoteServerThread.java

[44] tutorial/deployment/applet/examples/one-liners.txt

[45] tutorial/networking/sockets/index.html

[46] tutorial/deployment/applet/examples/TalkClientApplet.java

[47] tutorial/deployment/applet/examples/talk.html

[48] tutorial/deployment/applet/examples/TalkServer.java

[49] tutorial/deployment/applet/examples/TalkServerThread.java

[50] tutorial/uiswing/misc/access.html

[52] docs/technotes/guides/deployment/deployment-guide/autodl-files.html

[53] docs/technotes/guides/plugin/developer_guide/html_converter.html

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.31.41