Developing and Deploying Java Applets

«« Previous
Next »»

This lesson discusses the basics of Java applets, how to develop applets that interact richly with their environment, and how to deploy applets.

A Java 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 a browser. An applet must be a subclass of the java.applet.Applet class. The Applet class provides the standard interface between the applet and the browser environment.

Swing provides a special subclass of the Applet class called javax.swing.JApplet. The JApplet class should be used for all applets that use Swing components to construct their graphical user interfaces (GUIs).

The browser's Java Plug-in software manages the lifecycle of an applet.

Use a web server to test the examples in this lesson. The use of local applets is not recommended, and local applets are blocked when the security level setting in the Java Control Panel is set to High or Very High.

Note: Some features of Java applets may not work as described on Mac OS. This is because of the way the Java Plug-in software interfaces with browsers on Mac OS.

Getting Started With Applets


The HelloWorld applet shown next is a Java class that displays the string "Hello World".

Note: If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

Following is the source code for the HelloWorld applet:

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

public class HelloWorld extends JApplet {
    //Called when this applet is loaded into the browser.
    public void init() {
        //Execute a job on the event-dispatching thread; creating this applet's GUI.
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    JLabel lbl = new JLabel("Hello World");
                    add(lbl);
                }
            });
        } catch (Exception e) {
            System.err.println("createGUI didn't complete successfully");
        }
    }
}

An applet such as this is typically managed and run by the Java Plug-in software in the browser.

Defining an Applet Subclass

Every Java applet must define a subclass of the Applet or JApplet class. In the Hello World applet, this subclass is called HelloWorld. The following is the source for the HelloWorld class.

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

public class HelloWorld extends JApplet {
    //Called when this applet is loaded into the browser.
    public void init() {
        //Execute a job on the event-dispatching thread; creating this applet's GUI.
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    JLabel lbl = new JLabel("Hello World");
                    add(lbl);
                }
            });
        } catch (Exception e) {
            System.err.println("createGUI didn't complete successfully");
        }
    }
}

Java applets inherit significant functionality from the Applet or JApplet class, including the capabilities to communicate with the browser and 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 a root pane, which is the same top-level component structure as Swing's JFrame and JDialog components, whereas Applet provides just a basic panel.

An applet can extend the java.applet.Applet class when it does not use Swing's GUI components.

Methods for Milestones

The Applet class provides a framework for applet execution, defining methods that the system calls when milestones occur. Milestones are major events in an applet's life cycle. Most applets override some or all of these methods to respond appropriately to milestones.

init Method

The init method is useful for one-time initialization that doesn't take very long. The init method typically contains the code that you would normally put into a constructor. The reason applets don't usually have constructors is that they aren't guaranteed to have a full environment until their init method is called. Keep the init method short so that your applet can load quickly.

start Method

Every applet that performs tasks after initialization (except in direct response to user actions) must override the start method. The start method starts the execution of the applet. It is good practice to return quickly from the start method. If you need to perform computationally intensive operations it might be better to start a new thread for this purpose.

stop Method

Most applets that override the 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 an animation should stop trying to draw the animation when the user isn't viewing it.

destroy Method

Many applets don't need to override the destroy method because their stop method (which is called before destroy) will perform all tasks necessary to shut down the applet's execution. However, the destroy method is available for applets that need to release additional resources.

Note: 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.

Life Cycle of an Applet

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.

This section introduces a new applet, Simple, that uses all of these methods. Unlike Java applications, applets do not need to implement a main method.

Here is the Simple applet.

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.
The following is the source code for the Simple applet. This applet displays a descriptive string whenever it encounters a major milestone in its life, such as when the user first visits the page the applet is on.

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, the Applet class is extended, not the Swing JApplet class, as Swing components do not need to be added to this applet.

Loading the Applet

As a result of the applet being loaded, you should see the text "initializing... starting...". 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 and destroys the applet. The state of the applet is not preserved. When the user returns to the page, the browser intializes and starts a new instance of the applet.

Reloading the Applet

When you refresh or reload a browser page, the current instance of the applet is stopped and destroyed and a new instance is created.

Quitting the Browser

When the user quits the browser, the applet has the opportunity to stop itself and perform a final cleanup before the browser exits.

Applet's Execution Environment

A Java applet runs in the context of a browser. The Java Plug-in software in the browser controls the launch and execution of Java applets. The browser also has a JavaScript interpreter, which runs the JavaScript code on a web page. This topic describes the behavior of the Java Plug-in software released in Java Platform, Standard Edition 6 update 10.

Java Plug-in

The Java Plug-in software creates a worker thread for every Java applet. It launches an applet in an instance of the Java Runtime Environment (JRE) software. Normally, all applets run in the same instance of the JRE. The Java Plug-in software starts a new instance of the JRE in the following cases:

◉ When an applet requests to be executed in a specific version of the JRE.
◉ When an applet specifies its own JRE startup parameters, for example, the heap size. A new applet uses an existing JRE if its requirements are a subset of an existing JRE, otherwise, a new JRE instance is started.

An applet will run in an existing JRE if the following conditions are met:

◉ The JRE version required by the applet matches an existing JRE.
◉ The JRE's startup parameters satisfy the applet's requirements.

The following diagram shows how applets are executed in the JRE.

Developing and Deploying Java Applets

Java Plug-in and JavaScript Interpreter Interaction

Java applets can invoke JavaScript functions present in the web page. JavaScript functions are also allowed to invoke methods of an applet embedded on the same web page. The Java Plug-in software and the JavaScript interpreter orchestrate calls from Java code to JavaScript code and calls from JavaScript code to Java code.

The Java Plug-in software is multi-threaded, while the JavaScript interpreter runs on a single thread. Hence, to avoid thread-related issues, especially when multiple applets are running simultaneously, keep the calls between Java code and JavaScript code short, and avoid round trips, if possible.

Developing an Applet

An application designed using component-based architecture can be developed into a Java applet. Consider the example of a Java applet with a Swing-based graphical user interface (GUI). With component-based design, the GUI can be built with smaller building blocks or components. The following general steps are used to create an applet GUI:

◉ Create a class MyTopJPanel that is a subclass of javax.swing.JPanel. Lay out your applet's GUI components in the constructor of the MyTopJPanel class.
◉ Create a class called MyApplet that is a subclass of javax.swing.JApplet.
◉ In the init method of MyApplet, instantiate MyTopJPanel and set it as the applet's content pane.

The following sections explore these steps in greater detail by using the Dynamic Tree Demo applet. If you are not familiar with Swing, see Creating a GUI with Swing to learn more about using Swing GUI components.

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

Creating the Top JPanel Class

Create a class that is a subclass of JPanel. This top JPanel acts as a container for all your other UI components. In the following example, the DynamicTreePanel class is the topmost JPanel. The constructor of the DynamicTreePanel class invokes other methods to create and lay out the UI controls properly.

public class DynamicTreePanel extends JPanel implements ActionListener {
    private int newNodeSuffix = 1;
    private static String ADD_COMMAND = "add";
    private static String REMOVE_COMMAND = "remove";
    private static String CLEAR_COMMAND = "clear";
 
    private DynamicTree treePanel;

    public DynamicTreePanel() {
        super(new BorderLayout());
     
        //Create the components.
        treePanel = new DynamicTree();
        populateTree(treePanel);

        JButton addButton = new JButton("Add");
        addButton.setActionCommand(ADD_COMMAND);
        addButton.addActionListener(this);
     
        JButton removeButton = new JButton("Remove");
     
        // ...
     
        JButton clearButton = new JButton("Clear");
     
        // ...
     
        //Lay everything out.
        treePanel.setPreferredSize(
            new Dimension(300, 150));
        add(treePanel, BorderLayout.CENTER);

        JPanel panel = new JPanel(new GridLayout(0,3));
        panel.add(addButton);
        panel.add(removeButton);
        panel.add(clearButton);
        add(panel, BorderLayout.SOUTH);
    }
    // ...
}

Creating the Applet

For a Java applet that has a Swing-based GUI, create a class that is a subclass of javax.swing.JApplet. An applet that does not contain a Swing-based GUI can extend the java.applet.Applet class.

Override the applet's init method to instantiate your top JPanel class and create the applet's GUI. The init method of the DynamicTreeApplet class invokes the createGUI method in the AWT Event Dispatcher thread.

package appletComponentArch;

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

public class DynamicTreeApplet extends JApplet {
    //Called when this applet is loaded into the browser.
    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 complete successfully");
        }
    }
 
    private void createGUI() {
        //Create and set up the content pane.
        DynamicTreePanel newContentPane = new DynamicTreePanel();
        newContentPane.setOpaque(true);
        setContentPane(newContentPane);     
    }     
}

Benefits of Separating Core Functionality From the Final Deployment Mechanism

Another way to create an applet is to just remove the layer of abstraction (separate top JPanel) and lay out all the controls in the applet's init method itself. The downside to creating the GUI directly in the applet is that it will now be more difficult to deploy your functionality as a Java Web Start application, if you choose to do so later.

In the Dynamic Tree Demo example, the core functionality resides in the DynamicTreePanel class. It is now trivial to drop the DynamicTreePanel class into a JFrame and deploy as a Java Web Start application.

Deploying an Applet


To deploy your Java applet, first compile the source code, package it as a JAR file, and sign the JAR file.

Java applets can be launched in two ways.

◉ You can launch your applet by using Java Network Launch Protocol (JNLP). Applets launched by using JNLP have access to powerful JNLP APIs and extensions.

◉ Alternatively, you can launch an applet by specifying the applet's launch properties directly in the applet tag. However, this old way of deploying applets imposes severe security restrictions on the applet.

The Deployment Toolkit script contains useful JavaScript functions that can be used to deploy applets in a web page.

If you are unfamiliar with these deployment technologies, review the Deployment In-Depth lesson before proceeding further.

Here are some step-by-step instructions to package and deploy your applet. The Dynamic Tree Demo applet is used to illustrate applet deployment. You might want to set up build scripts to execute some of the following steps.

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

1. Compile your applet's Java code and make sure all class files and resources such as images are in a separate directory.

In the case of the DynamicTree Demo applet, the compiled classes are placed in the build/classes/appletComponentArch directory.

2. Create a text file that contains any JAR file manifest attributes that your applet needs.

For the DynamicTree Demo applet, create a file named mymanifest.txt in the build/classes directory, and add the Permissions, Codebase, and Application-Name attributes. The applet does not require access to the user's system resources, so use sandbox for the permissions. Use the domain from which you will load the sample for the code base, for example, myserver.com. Add the following attributes to the mymanifest.txt file.

Permissions: sandbox
Codebase: myserver.com
Application-Name: Dynamic Tree Demo

Other manifest attributes are available to restrict an applet to using only trusted code, and to provide security for applets that need to make calls between privileged Java code and sandbox Java code, or have JavaScript code that calls the applet.

3. Create a JAR file containing your applet's class files and resources. Include the manifest attributes in the mymanifest.txt file that you created in the previous step.
For example, the following command creates a JAR file with the class files in the build/classes/appletComponentArch directory and the manifest file in the build/classes directory.

% cd build/classes
% jar cvfm DynamicTreeDemo.jar mymanifest.txt appletComponentArch

4. Sign the JAR file for your applet and time stamp the signature. Use a valid, current code signing certificate issued by a trusted certificate authority to provide your users with assurance that it is safe to run the applet.

If you want to use a signed JNLP file for security, create the JNLP file as described in the next step and include it in the JAR file before the JAR file is signed.

5. Create a JNLP file that describes how your applet should be launched.

Here is the JNLP file used to launch the Dynamic Tree Demo applet.

The source for dynamictree_applet.jnlp follows:
 
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="" href="">
    <information>
        <title>Dynamic Tree Demo</title>
        <vendor>Dynamic Team</vendor>
    </information>
    <resources>
        <!-- Application Resources -->
        <j2se version="1.7+"
            href="http://java.sun.com/products/autodl/j2se" />
        <jar href="DynamicTreeDemo.jar" main="true" />

    </resources>
    <applet-desc
         name="Dynamic Tree Demo Applet"
         main-class="components.DynamicTreeApplet"
         width="300"
         height="300">
     </applet-desc>
     <update check="background"/>
</jnlp>                                 

Note that the security element for requesting additional permissions is not present in the JNLP file, therefore the applet runs only in the security sandbox.

The topic, Structure of the JNLP File, describes JNLP file syntax and options.

6. Create the HTML page that will display the applet. Invoke Deployment Toolkit functions to deploy the applet.

In our example, the Dynamic Tree Demo applet is deployed in AppletPage.html.

<body>
    <!-- ... -->
    <script src="https://www.java.com/js/deployJava.js"></script>
    <script>
        var attributes = {
            code:'components.DynamicTreeApplet',  width:300, height:300} ;
        var parameters = {jnlp_href: 'dynamictree_applet.jnlp'} ;
        deployJava.runApplet(attributes, parameters, '1.7');
    </script>
    <!-- ... -->
</body>

7. Place the applet's JAR file, JNLP file and HTML page in the appropriate folder(s).

For this example, place DynamicTreeDemo.jar, dynamictree_applet.jnlp, and AppletPage.html in the same directory on the local machine or a web server. A web server is preferred. To run from the local machine, you must add your application to the exception site list, which is managed from the Security tab of the Java Control Panel.

8. Open the applet's HTML page in a browser to view the applet. Agree to run the applet when prompted. Check the Java Console log for error and debugging messages.

Deploying With the Applet Tag

If you are not sure whether your end users' browsers will have the JavaScript interpreter enabled, you can deploy your Java applet by manually coding the <applet> HTML tag, instead of using the Deployment Toolkit functions. Depending on the browsers you need to support, you may need to deploy your Java applet using the <object> or <embed> HTML tag.

You can launch your applet using Java Network Launch Protocol (JNLP) or specify the launch attributes directly in the <applet> tag.

Preparing for Deployment

Follow the steps described in the Deploying An Applet topic to compile your source code, create and sign the JAR file, and create the JNLP file if necessary. The overall steps for deployment are still relevant. Only the contents of your HTML page containing the applet will change.

Manually Coding Applet Tag, Launching Using JNLP

The AppletPage_WithAppletTag.html page deploys the Dynamic Tree Demo applet with an <applet> tag that has been manually coded (meaning, the applet is not deployed using the Deployment Toolkit which automatically generates the required HTML). The applet is still launched using JNLP. The JNLP file is specified in the jnlp_href attribute.

<applet code = 'appletComponentArch.DynamicTreeApplet'
        jnlp_href = 'dynamictree_applet.jnlp'
        width = 300
        height = 300 />

Manually Coding Applet Tag, Launching Without JNLP

Using JNLP is the preferred way to deploy an applet, however, you can also deploy your applet without a JNLP file.

The AppletPage_WithAppletTagNoJNLP.html deploys the Dynamic Tree Demo applet as shown in the following code snippet.

<applet code = 'appletComponentArch.DynamicTreeApplet'
    archive = 'DynamicTreeDemo.jar'
    width = 300
    height = 300>
    <param name="permissions" value="sandbox" />
</applet>

where

◉ code is the name of the applet class.
◉ archive is the name of jar file containing the applet and its resources.
◉ width is the width of the applet.
◉ height is the height of the applet.
◉ permissions indicates if the applet runs in the security sandbox. Specify "sandbox" for the value to run in the sandbox. Specify "all-permissions" to run outside the sandbox. If the permissions parameter is not present, signed applets default to "all-permissions" and unsigned applets default to "sandbox".

Doing More With Applets

The Java applet API enables you to take advantage of the close relationship that applets have with browsers. The API is provided by the javax.swing.JApplet class and the java.applet.AppletContext interface. The applet execution architecture enables applets to interact with their environment to produce a rich user experience. An applet can manipulate its parent web page, interact with JavaScript code in the web page, find other applets running in the same web page, and much more.

Advanced capabilities of Java applets are explored in subsequent topics.

Finding and Loading Data Files

Whenever a Java applet needs to load data from a file that is 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. For locally deployed applets, the getCodeBase method returns null.

The document base, returned by the JApplet getDocumentBase method, specifies the directory of the HTML page that contains the applet. For locally deployed applets, the getDocumentBase method returns null.

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 access directories above the code base or document base. Also, because untrusted applets cannot read files except for those files on the applet's originating host, the document base is generally not useful if the document and the untrusted applet reside on different servers.

The JApplet class defines convenient forms of image-loading and sound-loading methods that enable you to 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 the following figure.


To create an Image object that uses the a.gif image file under imgDir, the applet can use the following code:

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

Defining and Using Applet Parameters

Parameters are to Java applets what command-line arguments are to applications. They enable 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.

Specifying an Applet's Input Parameters

You can specify an applet's input parameters in the applet's Java Network Launch Protocol (JNLP) file or in the <parameter> element of the <applet> tag. It is usually better to specify the parameters in the applet's JNLP file so that the parameters can be supplied consistently even if the applet is deployed on multiple web pages. If the applet's parameters will vary by web page, then you should specify the parameters in the <parameter> element of the <applet> tag.

Consider an applet that takes three parameters. The paramStr and paramInt parameters are specified in the applet's JNLP file, applettakesparams.jnlp.

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="" href="">
    <!-- ... -->
    <applet-desc
         name="Applet Takes Params"
         main-class="AppletTakesParams"
         width="800"
         height="50">
             <param name="paramStr"
                 value="someString"/>
             <param name="paramInt" value="22"/>
     </applet-desc>
     <!-- ... -->
</jnlp>

The paramOutsideJNLPFile parameter is specified in the parameters variable passed to the Deployment Toolkit script's runApplet function in AppletPage.html.

<html>
  <head>
    <title>Applet Takes Params</title>
    <meta http-equiv="Content-Type" content="text/html;
        charset=windows-1252">
  </head>
  <body>
    <h1>Applet Takes Params</h1>

    <script
      src="https://www.java.com/js/deployJava.js"></script>
    <script>
        var attributes = { code:'AppletTakesParams.class',
            archive:'applet_AppletWithParameters.jar',
            width:800, height:50 };
        var parameters = {jnlp_href: 'applettakesparams.jnlp',
            paramOutsideJNLPFile: 'fooOutsideJNLP' };
        deployJava.runApplet(attributes, parameters, '1.7');
    </script>

  </body>
</html>

Retrieving the Applet's Input Parameters

You can retrieve the applet's input parameters by using the getParameter method of the Applet class. The AppletTakesParams.java applet retrieves and displays all its input parameters (paramStr, paramInt, and paramOutsideJNLPFile).

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

public class AppletTakesParams extends JApplet {
    public void init() {
        final String  inputStr = getParameter("paramStr");     
        final int inputInt = Integer.parseInt(getParameter("paramInt"));
        final String inputOutsideJNLPFile = getParameter("paramOutsideJNLPFile");

        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    createGUI(inputStr, inputInt, inputOutsideJNLPFile);
                }
            });
        } catch (Exception e) {
            System.err.println("createGUI didn't successfully complete");
        }
    }
    private void createGUI(String inputStr, int inputInt, String inputOutsideJNLPFile) {
        String text = "Applet's parameters are -- inputStr: " + inputStr +
                ",   inputInt: " + inputInt +
                ",   paramOutsideJNLPFile: " + inputOutsideJNLPFile;
        JLabel lbl = new JLabel(text);
        add(lbl);
    }
}

The AppletTakesParams applet is shown next.

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

Displaying Short Status Strings

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

Never put crucial information in the status line. If many users might need the information, display that information within the applet area. If only a few, sophisticated users might need the information, consider sending the information to standard output.

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

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

Here is an example of its use:

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

Note: Don't put scrolling text in the status line. Browser users find such behavior highly annoying.

Displaying Documents in the Browser

A Java applet can load a web page in a browser window using the showDocument methods in the java.applet.AppletContext class.

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 instructs the browser to display the document at the specified URL, without specifying the window in which to display the document.

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

◉ "_blank" – Display the document in a new, nameless window.
◉ "windowName" – Displays 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".

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

The following applet enables you try every argument of both forms of showDocument. The applet opens a window that lets you type in a URL and choose an option for the targetWindow argument. When you press Return or click the Show document button, the applet calls showDocument.

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

Following is the applet code that calls showDocument. Here is the whole program, ShowDocument.

        ...//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 */);
                }
            }
        ...

Invoking JavaScript Code From an Applet

Java applets can invoke JavaScript functions present in the same web page as the applet. The LiveConnect Specification describes details about how JavaScript code communicates with Java code.

The netscape.javascript.JSObject class enables Java applets to retrieve a reference to JavaScript objects and interact with the web page. The Data Summary applet described next invokes JavaScript code to retrieve information from the web page and writes a data summary back to the web page.

Assume you have a web page with a few JavaScript functions. The example AppletPage.html has JavaScript functions to retrieve age, address, and phone numbers. There is also a variable called userName which has no value at the outset.

<head>
<title>Data Summary Applet Page - Java to JavaScript LiveConnect</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"/>
<script language="javascript">
    var userName = "";
 
    // returns number
    function getAge() {
        return 25;
    }
    // returns an object
    function address() {
        this.street = "1 Example Lane";
        this.city = "Santa Clara";
        this.state = "CA";
    }
    // returns an array
    function getPhoneNums() {
        return ["408-555-0100", "408-555-0102"];
    }
    function writeSummary(summary) {
        summaryElem =
            document.getElementById("summary");
        summaryElem.innerHTML = summary;
    }
    </script>

    <!-- ... -->   
</head>
<body>
    <script src =
      "https://www.java.com/js/deployJava.js"></script>
    <script>
        <!-- ... -->
        deployJava.runApplet(attributes, parameters, '1.6');
    </script>       
    <!-- ... -->
    <p id="summary"/>  // this HTML element contains
                             // the summary
    <!-- ... -->
</body>

Next, consider an applet class called DataSummaryApplet. The DataSummaryApplet class performs the following operations.

◉ Invokes the JSObject's setMember method to set the userName variable to "John Doe".
◉ Retrieves the age, address, and phone numbers and builds a string containing a summary of this data.
◉ Invokes the writeSummary JavaScript function to write the summary back to the web page.

This applet first needs to retrieve a reference to JSObject as follows:

...
JSObject window = JSObject.getWindow(this);
...

Put the preceding statement in a try ...catch.. block to handle netscape.javascript.JSException.

Now that the applet has a reference to JSObject, it can invoke the relevant JavaScript functions by using the eval and call methods of JSObject.

package javatojs;

import java.applet.Applet;
import netscape.javascript.*; // add plugin.jar to classpath during compilation

public class DataSummaryApplet extends Applet {
    public void start() {
        try {
            JSObject window = JSObject.getWindow(this);

            String userName = "John Doe";

            // set JavaScript variable
            window.setMember("userName", userName);

            // invoke JavaScript function
            Number age = (Number) window.eval("getAge()");

            // get a JavaScript object and retrieve its contents
            JSObject address = (JSObject) window.eval("new address();");
            String addressStr = (String) address.getMember("street") + ", " +
                    (String) address.getMember("city") + ", " +
                    (String) address.getMember("state");

            // get an array from JavaScript and retrieve its contents
            JSObject phoneNums = (JSObject) window.eval("getPhoneNums()");
            String phoneNumStr = (String) phoneNums.getSlot(0) + ", " +
                    (String) phoneNums.getSlot(1);

            // dynamically change HTML in page; write data summary
            String summary = userName + " : " + age + " : " +
                    addressStr + " : " + phoneNumStr;
            window.call("writeSummary", new Object[] {summary})   ;
        } catch (JSException jse) {
            jse.printStackTrace();
        }
    }
}

To compile Java code that has a reference to classes in the netscape.javascript package, include <your JDK path>/jre/lib/plugin.jar in your classpath. At runtime, the Java Plug-in software automatically makes these classes available to applets.

The Data Summary applet displays the following result on the web page:

Result of applet's Java calls to JavaScript on this page
             
John Doe : 25 : 1 Example Lane, Santa Clara, CA : 408-555-0100, 408-555-0102

Invoking Applet Methods From JavaScript Code

JavaScript code on a web page can interact with Java applets embedded on the page. JavaScript code can perform operations such as the following:

◉ Invoke methods on Java objects
◉ Get and set fields in Java objects
◉ Get and set Java array elements

The LiveConnect Specification describes details about how JavaScript code communicates with Java code.

Security warnings are shown when JavaScript code makes calls to a Java applet. To suppress these warnings, add the Caller-Allowable-Codebase attribute to the JAR file manifest. Specify the location of the JavaScript code that is allowed to make calls to the applet.

This topic explores JavaScript code to Java applet communication using the Math applet example. The MathApplet class and supporting Calculator class provide a set of public methods and variables. The JavaScript code on the web page invokes and evaluates these public members to pass data and retrieve calculated results.

Math Applet and Related Classes

Here is the source code for the MathApplet class. The getCalculator method returns a reference to the Calculator helper class.

package jstojava;
import java.applet.Applet;

public class MathApplet extends Applet{

    public String userName = null;
       
    public String getGreeting() {
        return "Hello " + userName;
    }
 
    public Calculator getCalculator() {
        return new Calculator();
    }
 
    public DateHelper getDateHelper() {
        return new DateHelper();
    }
 
    public void printOut(String text) {
        System.out.println(text);
    }
}

The methods in the Calculator class let the user set two values, add numbers, and retrieve the numbers in a range.

package jstojava;

public class Calculator {
    private int a = 0;
    private int b = 0; // assume b > a
 
    public void setNums(int numA, int numB) {
        a = numA;
        b = numB;
    }
 
    public int add() {
        return a + b;
    }
 
    public int [] getNumInRange() { 
        int x = a;
        int len = (b - a) + 1;
        int [] range = new int [len];
        for (int i = 0; i < len; i++) {
            range[i]= x++;
            System.out.println("i: " + i + " ; range[i]: " + range[i]);
        }
        return range;
    }
}

The getDate method of the DateHelper class returns the current date.

package jstojava;
import java.util.Date;
import java.text.SimpleDateFormat;

public class DateHelper {
 
    public static String label = null;
     
    public String getDate() {
        return label + " " + new SimpleDateFormat().format(new Date());
    }

}

Deploying the Applet

Deploy the applet in a web page, AppletPage.html When deploying the applet, make sure that you specify an id for the applet. The applet id is used later to obtain a reference to the applet object.

<script src=
  "https://www.java.com/js/deployJava.js"></script>
<script>
    <!-- applet id can be used to get a reference to
    the applet object -->
    var attributes = { id:'mathApplet',
        code:'jstojava.MathApplet',  width:1, height:1} ;
    var parameters = { jnlp_href: 'math_applet.jnlp'} ;
    deployJava.runApplet(attributes, parameters, '1.6');
</script>

Next, add some JavaScript code to the AppletPage.html web page. The JavaScript code can use the applet id as a reference to the applet object and invoke the applet's methods. In the example shown next, the JavaScript code sets the applet's public member variables, invokes public methods, and retrieves a reference to another object referenced by the applet (Calculator). The JavaScript code is able to handle primitive, array, and object return types.

<script language="javascript">
    function enterNums(){
        var numA = prompt('Enter number \'a\'?','0');
        var numB = prompt(
            'Enter number \'b\' (should be greater than number \'a\' ?','1');
        // set applet's public variable
        mathApplet.userName = "John Doe";

        // invoke public applet method
        var greeting = mathApplet.getGreeting();

        // get another class referenced by applet and
        // invoke its methods
        var calculator = mathApplet.getCalculator();
        calculator.setNums(numA, numB);

        // primitive datatype returned by applet
        var sum = calculator.add();

        // array returned by applet
        var numRange = calculator.getNumInRange();

        // check Java console log for this message
        mathApplet.printOut("Testing printing to System.out");

        // get another class, set static field and invoke its methods
        var dateHelper = mathApplet.getDateHelper();
        dateHelper.label = "Today\'s date is: ";
        var dateStr = dateHelper.getDate();
        <!-- ... -->
</script>

The Math applet displays the following results on the web page when the number a = 0 and b = 5:

Results of JavaScript to Java Communication

Hello John Doe

a = 0 ; b = 5

Sum: 5

Numbers in range array: [ 0, 1, 2, 3, 4, 5 ]

Today's date is: 5/28/13 4:12 PM //shows current date

Open AppletPage.html in a browser to view the Math applet.

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

Handling Initialization Status With Event Handlers

An applet cannot handle requests from JavaScript code in the web page until the applet has been initialized. A call to an applet method or access to an applet variable from JavaScript code will be blocked until the applet's init() method is complete or the applet first invokes JavaScript code from the web page in which it is deployed. As the JavaScript implementation is single-threaded in many browsers, the web page may appear to be frozen during applet startup.

Beginning in the JDK 7 release, you can check the status variable of the applet while it is loading to determine if the applet is ready to handle requests from JavaScript code. You can also register event handlers that will automatically be invoked during various stages of applet initialization. To leverage this functionality, the applet should be deployed with the java_status_events parameter set to "true".

In the Status and Event Handler example, JavaScript code registers an onLoad handler with the applet. The onLoad handler is automatically invoked by the Java Plug-in software when the applet has been initialized. The onLoad handler invokes other methods of the applet to draw the graph on the web page. The init method of the DrawingApplet class sleeps for two seconds to simulate a long applet initialization period.

The following steps describe how to register event handlers and check an applet's status. See Applet Status and Event Handlers for a complete list of applet status values and applet events for which event handlers can be registered.

1. Create a JavaScript function to register event handlers. The following code snippet shows the registerAppletStateHandler function that registers an onLoad event handler if the applet has not already loaded.
<script>
<!-- ... -->
    var READY = 2;
    function registerAppletStateHandler() {
        // register onLoad handler if applet has
        // not loaded yet
        if (drawApplet.status < READY)  {               
            drawApplet.onLoad = onLoadHandler;
        } else if (drawApplet.status >= READY) {
            // applet has already loaded or there
            // was an error
            document.getElementById("mydiv").innerHTML =
              "Applet event handler not registered because applet status is: "
               + drawApplet.status; 
        }
    }
 
    function onLoadHandler() {
        // event handler for ready state
        document.getElementById("mydiv").innerHTML =
            "Applet has loaded";
        draw();
    }
<!-- ... -->
</script>     

2. Invoke the previously created registerAppletStateHandler function in the body tag's onload method. This ensures that the HTML tag for the applet has been created in the Document Object Model (DOM) tree of the web page before the applet's event handlers are registered.

<body onload="registerAppletStateHandler()">

3. Deploy the applet with the java_status_events parameter set to "true".

<script src=
  "https://www.java.com/js/deployJava.js"></script>
<script>
    // set java_status_events parameter to true
    var attributes = { id:'drawApplet',
        code:'DrawingApplet.class',
        archive: 'applet_StatusAndCallback.jar',
        width:600, height:400} ;
    var parameters = {java_status_events: 'true', permissions:'sandbox' } ;
    deployJava.runApplet(attributes, parameters, '1.7');
</script>

Open AppletPage.html in a browser to view the behavior of applet event handlers. In the AppletPageUpdatedDuringLoading.html page, the status variable of the applet is checked to determine if the applet has been loaded. Based on the status, the web page is continuously updated while the applet is being loaded.

Manipulating DOM of Applet's Web Page

Every web page is composed of a series of nested objects. These objects make up the Document Object Model (DOM). A Java applet can traverse and modify objects of its parent web page using the Common DOM API.

Consider an example of a Java applet that dumps the contents of its parent web page.

In order to traverse and manipulate the DOM tree, you must first obtain a reference to the Document object for the web page. You can do so by using the getDocument method in the com.sun.java.browser.plugin2.DOM class. Here is a code snippet that retrieves a reference to a Document object in the DOMDump applet's start method. See inline comments in the code.

public void start() {
    try {
        // use reflection to get document
        Class c =
          Class.forName("com.sun.java.browser.plugin2.DOM");
        Method m = c.getMethod("getDocument",
          new Class[] { java.applet.Applet.class });
     
        // cast object returned as HTMLDocument;
        // then traverse or modify DOM
        HTMLDocument doc = (HTMLDocument) m.invoke(null,
            new Object[] { this });
        HTMLBodyElement body =
            (HTMLBodyElement) doc.getBody();
        dump(body, INDENT);
    } catch (Exception e) {
        System.out.println("New Java Plug-In not available");
        // In this case, you could fallback to the old
        // bootstrapping mechanism available in the
        // com.sun.java.browser.plugin.dom package
    }
}

Now that you have a reference to the Document object, you can traverse and modify the DOM tree using the Common DOM API. The DOMDump applet traverses the DOM tree and writes its contents to the Java Console log.

private void dump(Node root, String prefix) {
    if (root instanceof Element) {
        System.out.println(prefix +
            ((Element) root).getTagName() +
            " / " + root.getClass().getName());
    } else if (root instanceof CharacterData) {
        String data =
            ((CharacterData) root).getData().trim();
        if (!data.equals("")) {
            System.out.println(prefix +
                "CharacterData: " + data);
        }
    } else {
        System.out.println(prefix +
            root.getClass().getName());
    }
    NamedNodeMap attrs = root.getAttributes();
    if (attrs != null) {
        int len = attrs.getLength();
        for (int i = 0; i < len; i++) {
            Node attr = attrs.item(i);
            System.out.print(prefix + HALF_INDENT +
                "attribute " + i + ": " +
                attr.getNodeName());
            if (attr instanceof Attr) {
                System.out.print(" = " +
                    ((Attr) attr).getValue());
            }
            System.out.println();
        }
    }

    if (root.hasChildNodes()) {
        NodeList children = root.getChildNodes();
        if (children != null) {
            int len = children.getLength();
            for (int i = 0; i < len; i++) {
                dump(children.item(i), prefix +
                    INDENT);
            }
        }
    }
}

Open AppletPage.html in a browser to view the DOMDump applet running. Check the Java Console log for a dump of the DOM tree of the web page.

Displaying a Customized Loading Progress Indicator

A Java applet can display a customized loading progress indicator that shows the progress of download of the applet's resources as well as other applet specific data..

Consider the Weather applet and the CustomProgress class to understand how to implement a customized loading progress indicator for a Java applet. For the purpose of demonstrating a large and prolonged download, this applet's JAR file has been artifically inflated and the customprogress_applet.jnlp file specifies additional JAR files as resources.

Developing a Customized Loading Progress Indicator
To develop a customized loading progress indicator for your applet, create a class that implements the DownloadServiceListener interface.

The constructor of the loading progress indicator class will vary depending on how the UI should be displayed and the capabilities needed by the class. The following guidelines should be applied:

◉ To display the loading progress indicator in a separate top level window, create a constructor that does not have any parameters.
◉ To display the loading progress indicator for an applet in the applet's container, create a constructor that takes an Object as a parameter. The Object argument can be typecast to an instance of the java.awt.Container class.
◉ If the loading progress indicator class needs to access the applet's parameters, create two constructors as follows:
◉ Create a constructor that takes an Object as a parameter as described previously.
◉ Create a constructor that takes two parameters of type Object. The first argument can be typecast to an instance of the java.awt.Container class and the second argument can be typecast to an instance of the java.applet.AppletStub class.

The Java Plug-in software will invoke the appropriate constructor depending on the capabilities of the JRE software on the client machine.

import javax.jnlp.DownloadServiceListener;
import java.awt.Container;
import java.applet.AppletStub;
import netscape.javascript.*;

// ...

public class CustomProgress implements DownloadServiceListener { 
    Container surfaceContainer = null;
    AppletStub appletStub = null;
    JProgressBar progressBar = null;
    JLabel statusLabel = null;
    boolean uiCreated = false;

    public CustomProgress(Object surface) {
       init(surface, null);
    }

    public CustomProgress(Object surface, Object stub) {
        init(surface, stub);
    }

    public void init(Object surface, Object stub) {
        try {
            surfaceContainer = (Container) surface;
            appletStub = (AppletStub) stub;
        } catch (ClassCastException cce) {
            // ...
        }
    }
// ...


The following code snippet shows how to build the UI for the loading progress indicator. Use the instance of the java.applet.AppletStub class to retrieve the applet's parameters. Invoke the JSObject.getWindow(null) method to obtain a reference to the applet's parent web page and invoke JavaScript code on that page.

private void create() {
    JPanel top = createComponents();
    if (surfaceContainer != null) {
        // lay out loading progress UI in the given
        // Container
        surfaceContainer.add(top, BorderLayout.NORTH);
        surfaceContainer.invalidate();
        surfaceContainer.validate();
    }   
}
private JPanel createComponents() {
    JPanel top = new JPanel();
    // ...
    // get applet parameter using an instance of the
    // AppletStub class "tagLine" parameter specified
    // in applet's JNLP file
    String tagLine = "";
    if (appletStub != null) {
        tagLine = appletStub.getParameter("tagLine");
    }
    String lblText = "<html><font color=red size=+2>JDK
        Documentation</font><br/>" +
        tagLine + " <br/></html>";
    JLabel lbl = new JLabel(lblText);
    top.add(lbl, BorderLayout.NORTH);

    // use JSObject.getWindow(null) method to retrieve
    // a reference to the web page and make JavaScript
    // calls. Duke logo displayed if displayLogo variable
    // set to "true" in the web page
    String displayLogo = "false"; 
    JSObject window = JSObject.getWindow(null);     
    if (window != null) {
        displayLogo = (String)window.getMember("displayLogo");
    }
    if (displayLogo.equals("true")) {
        lbl = new JLabel();
        ImageIcon logo = createImageIcon("images/DukeWave.gif", "logo");
        lbl.setIcon(logo);
        top.add(lbl, BorderLayout.EAST);
    }

    statusLabel = new JLabel(
        "html><font color=green size=-2>" +
        "Loading applet...</font></html>");
    top.add(statusLabel, BorderLayout.CENTER);

    // progress bar displays progress
    progressBar = new JProgressBar(0, 100);
    progressBar.setValue(0);
    progressBar.setStringPainted(true);
    top.add(progressBar, BorderLayout.SOUTH);

    return top;
}

Create and update the progress indicator in the following methods based on the overallPercent argument. These methods are invoked regularly by the Java Plug-in software to communicate progress of the applet's download. Java Plug-in software will always send a message when download and validation of resources is 100% complete.

public void progress(URL url, String version,
                     long readSoFar, long total,
                     int overallPercent) {     
    // check progress of download and update display
    updateProgressUI(overallPercent);
}

public void upgradingArchive(java.net.URL url,
                  java.lang.String version,
                  int patchPercent,
                  int overallPercent) {
    updateProgressUI(overallPercent);
}

public void validating(java.net.URL url,
            java.lang.String version,
            long entry,
            long total,
            int overallPercent) {
    updateProgressUI(overallPercent);
}

private void updateProgressUI(int overallPercent) {
    if (!uiCreated && overallPercent > 0
        && overallPercent < 100) {
        // create custom progress indicator's
        // UI only if there is more work to do,
        // meaning overallPercent > 0 and
        // < 100 this prevents flashing when
        // RIA is loaded from cache
        create();
        uiCreated = true;         
    }
    if (uiCreated) {
        progressBar.setValue(overallPercent);
    }
}

Compile the loading progress indicator class and build a JAR file with all the resources needed to display the loading progress indicator. Include the following JAR files in your classpath to enable compilation:

◉ <your JRE directory>/lib/javaws.jar
◉ <your JRE directory>/lib/plugin.jar – This JAR file is required only if your loading progress indicator class uses the JSObject.getWindow method to invoke JavaScript code in the applet's parent web page.

The loading progress indicator class is now ready for use. The next step is to specify this loading progress indicator JAR file as your applet's loading progress indicator.

Specifying a Loading Progress Indicator for an Applet

To specify a customized loading progress indicator for an applet, include the following information in the applet's JNLP file:

- jar tag with the download="progress" attribute
- progress-class attribute with the fully qualified name of the loading progress class.

The following code snippet from the customprogress_applet.jnlp file displays the usage of the download="progress" and progress-class attributes.

<jnlp spec="1.0+"
  codebase="https://docs.oracle.com/javase/tutorial/deployment"
  href="">
  <!-- ... -->
  <resources>
    <!-- ... -->
    <jar
      href="applet/examples/dist/applet_AppletWithCustomProgressIndicator"
      main="true" /> 
    <jar
      href="applet/examples/dist/applet_CustomProgressIndicator/applet_CustomProgressIndicator.jar"
     download="progress" />
  </resources>
  <applet-desc
     name="customprogressindicatordemo.WeatherApplet"
     main-class="customprogressindicatordemo.WeatherApplet"
     progress-class="customprogressindicator.CustomProgress"
     width="600"
     height="200">
     <param
       name="tagLine"
       value="Information straight from the horse's mouth!"/>
  </applet-desc>
<!-- ... -->
</jnlp>

Deploy the applet in a web page. Open AppletPage.html in a web browser to view the loading progress indicator for the Weather applet.

Note:  To view the example properly, you need to install at least the Java SE Development Kit (JDK) 6 update 21 release.

Note: If you have viewed this applet before, clear your cache by using the Java Control Panel before viewing the applet again. You will not be able to see a progress indicator for a previously cached applet.

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

Integrating the Loading Progress Indicator With Applet UI

You can also integrate the loading progress indicator into the applet's UI. Open AppletPage.html in a web browser to view the loading progress indicator integrated into the Weather applet's UI.

Writing Diagnostics to Standard Output and Error Streams

A Java applet can write messages to the standard output and standard error streams. Writing diagnostics to standard output can be an invaluable tool when you are debugging a Java applet.

The following code snippet writes messages to the standard output stream and the standard error stream.

// Where instance variables are declared:
boolean DEBUG = true;
// ...
// Later, when we want to print some status:
if (DEBUG) {
    try {
        // ...
        //some code that throws an exception
        System.out.
            println("Called someMethod(" + x + "," + y + ")");
    } catch (Exception e) {
        e.printStackTrace()
    }
}

Check the Java Console log for messages written to the standard output stream or standard error stream. To store messages in a log file, enable logging in the Java Control Panel. Messages will be written to a log file in the user's home directory (for example, on Windows, the log file might be in C:\Documents and Settings\someuser\Application Data\Sun\Java\Deployment\log).

Note: Be sure to disable all debugging output before you release your applet.

Developing Draggable Applets

A Java applet that is deployed by specifying the draggable parameter can be dragged outside of the browser and dynamically transformed into a Java Web Start application. The Java applet can be dragged by pressing the Alt key and the left mouse button and dragging the mouse. When the drag operation begins, the applet is removed from its parent container (Applet or JApplet) and placed in a new undecorated top-level window (Frame or JFrame). A small floating Close button is displayed next to the dragged applet. When the floating Close button is clicked, the applet is placed back in the browser. Java applets that can be dragged out of the browser shall henceforth be referred to as draggable applets.

You can customize the behavior of a draggable applet in the following ways:

◉ You can change the keystroke and mouse button sequence that is used to drag the applet outside of the browser.
◉ You can add a desktop shortcut that can be used to launch your application outside of the browser.
◉ You can define how the applet should be closed after it has been dragged outside of the browser.

The following sections describe how to implement and customize a draggable applet. The MenuChooserApplet class is used to demonstrate the development and deployment of draggable applets. Open AppletPage.html in a browser to view the Menu Chooser applet on a new page.

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

Enabling the Capability to Drag an Applet

You can enable the capability to drag an applet by setting the draggable parameter to true when deploying the applet, as shown in the following code snippet:

<script src="https://www.java.com/js/deployJava.js"></script>
<script>
    var attributes = { code:'MenuChooserApplet', width:900, height:300 };
    var parameters = { jnlp_href: 'draggableapplet.jnlp', draggable: 'true' };
    deployJava.runApplet(attributes, parameters, '1.6');
</script>

Changing the Keystroke and Mouse Button Sequence That Is Used to Drag an Applet

You can change the keystroke and mouse button sequence that is used to drag an applet by implementing the isAppletDragStart method. In the following code snippet, the applet can be dragged by pressing the left mouse button and dragging the mouse:

 public boolean isAppletDragStart(MouseEvent e) {
        if(e.getID() == MouseEvent.MOUSE_DRAGGED) {
            return true;
        } else {
            return false;
        }
    }

Enabling the Addition of a Desktop Shortcut When the Applet Is Disconnected From the 
Browser

If the user closes the browser window or navigates away from the page after dragging an applet outside of the page, the applet is said to be disconnected from the browser. You can create a desktop shortcut for the applet when the applet is disconnected from the browser. The desktop shortcut can be used to launch the application outside of the browser. To enable the creation of a desktop shortcut, add the offline-allowed and shortcut tags to the applet's Java Network Launch Protocol (JNLP) file.

<information>
    <!-- ... -->
    <offline-allowed />
    <shortcut online="false">
        <desktop />
    </shortcut>
</information>

Note: Depending on the setting for Shortcut Creation in the user's Java Control Panel, the user might be prompted for confirmation before the shortcut is created.

Defining How the Applet Should Be Closed

You can define how your applet can be closed. For example, your Swing applet could have a JButton to close the applet instead of relying on the default floating Close button.

The Java Plug-in software gives the applet an instance of the ActionListener class. This instance of the ActionListener class, also referred to as the close listener, can be used to modify the default close behavior of the applet.

To define how the applet should be closed, implement the setAppletCloseListener and appletRestored methods in your applet.

In the following code snippet, the MenuChooserApplet class receives the close listener and passes it on to the instance of the MenuItemChooser class:

MenuItemChooser display = null;
// ...
display = new MenuItemChooser();
// ...
public void setAppletCloseListener(ActionListener cl) {
    display.setCloseListener(cl);
}

public void appletRestored() {
    display.setCloseListener(null);
}

The MenuItemChooser class is responsible for controlling the applet's user interface. The MenuItemChooser class defines a JButton labeled "Close." The following code is executed when the user clicks this Close button:

private void close() {
    // invoke actionPerformed of closeListener received
    // from the Java Plug-in software.
    if (closeListener != null) {
        closeListener.actionPerformed(null);
    }
}

Requesting and Customizing Applet Decoration

Beginning in the Java SE 7 release, when deploying an applet, you can specify that the window of dragged applet should be decorated with the default or customized window title.

To enable window decoration of a dragged applet, specify the java_decorated_frame parameter with a value of "true". To enable a customized window title, specify the java_applet_title parameter also. The value of this parameter should be the text of the window title.

<script src="https://www.java.com/js/deployJava.js"></script>
<script>
    var attributes =
      { code:'SomeDraggableApplet', width:100, height:100 };
    var parameters =
      { jnlp_href: 'somedraggableapplet.jnlp',
          java_decorated_frame: 'true',
          java_applet_title: 'A Custom Title' 
      };
    deployJava.runApplet(attributes, parameters, '1.7');
</script>

The java_decorated_frame and java_applet_title parameters can also be specified in the applet's JNLP file as shown in the following code snippet:

<applet-desc main-class="SayHello" name="main test" height="150" width="300">
    <param name="java_decorated_frame" value="true" />
    <param name="java_applet_title" value="" />
</applet-desc>

Communicating With Other Applets

A Java applet can communicate with other Java applets by using JavaScript functions in the parent web page. JavaScript functions enable communication between applets by receiving messages from one applet and invoking methods of other applets. See the following topics for more information about the interaction between Java code and JavaScript code:

◉ Invoking JavaScript Code From an Applet
◉ Invoking Applet Methods From JavaScript Code

You should avoid using the following mechanisms to find other applets and share data between applets:

◉ Avoid using static variables to share data between applets.

◉ Do not use the getApplet and getApplets methods of the AppletContext class to find other applets. These methods only find applets that are running in the same instance of the Java Runtime Environment software.

Applets must originate from the same directory on the server in order to communicate with each other.

The Sender and Receiver applets are shown next. When a user clicks the button to increment the counter, the Sender applet invokes a JavaScript function to send a request to the Receiver applet. Upon receiving the request, the Receiver applet increments a counter variable and displays the value of the variable.

Sender Applet

Receiver Applet

Note:  If you don't see the example running, you might need to enable the JavaScript interpreter in your browser so that the Deployment Toolkit script can function properly.

To enable communication with another applet, obtain a reference to an instance of the netscape.javascript.JSObject class. Use this instance to invoke JavaScript functions. The Sender applet uses an instance of the netscape.javascript.JSObject class to invoke a JavaScript function called sendMsgToIncrementCounter.

try {
    JSObject window = JSObject.getWindow(this);
    window.eval("sendMsgToIncrementCounter()");
} catch (JSException jse) {
    // ...
}

Note: To compile Java code that has a reference to classes in the netscape.javascript package, include <your JDK path>/jre/lib/plugin.jar in your classpath. At runtime, the Java Plug-in software automatically makes these classes available to applets.

Write the JavaScript function that will receive requests from one applet and invoke methods of another applet on the web page. The sendMsgToIncrementCounter JavaScript function invokes the Receiver applet's incrementCounter method.

<script>
    function sendMsgToIncrementCounter() {
        var myReceiver = document.getElementById("receiver");
        myReceiver.incrementCounter();
    }
<script>

Note that the JavaScript code uses the name receiver to obtain a reference to the Receiver applet on the web page. This name should be the same as the value of the id attribute that is specified when you deploy the Receiver applet.

The Receiver applet's incrementCounter method is shown next.

public void incrementCounter() {
    ctr++;
    String text = " Current Value Of Counter: "
        + (new Integer(ctr)).toString();
    ctrLbl.setText(text);
}

Deploy the applets on the web page as shown in the following code snippet. You can view the Sender and Receiver applets and associated JavaScript code in AppletPage.html.

<!-- Sender Applet -->
<script src="https://www.java.com/js/deployJava.js"></script>
<script>
    var attributes = { code:'Sender.class',
        archive:'examples/dist/applet_SenderReceiver/applet_SenderReceiver.jar',
        width:300, height:50} ;
    var parameters = { permissions:'sandbox' };
    deployJava.runApplet(attributes, parameters, '1.6');
</script>

<!-- Receiver Applet -->
<script>
    var attributes = { id:'receiver', code:'Receiver.class',
        archive:'examples/dist/applet_SenderReceiver/applet_SenderReceiver.jar',
        width:300, height:50} ;
    var parameters = { permissions:'sandbox' };
    deployJava.runApplet(attributes, parameters, '1.6');
</script>

Working With a Server-Side Application

Java applets, like other Java programs, can use the API defined in the java.net package to communicate across the network. A Java applet can communicate with server applications that run on the same host as the applet. This communication does not require any special setup on the server.

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

When the applet is deployed to a web server, use the Applet getCodeBase method and the java.net.URL getHost method to determine which host the applet came from, as follows:

String host = getCodeBase().getHost();

If the applet is deployed locally, the getCodeBase method returns null. Use of a web server is recommended.

After you have the correct host name, you can use all the networking code that is documented in the Custom Networking trail.

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.

Network Client Applet Example

The QuoteClientApplet class allows you to fetch quotations from a server-side application that runs on the same host as this applet. This class also displays the quotation received from the server.

The QuoteServer.java and QuoteServerThread.java classes make up the server-side application that returns quotations. Here's a text file ( one-liners.txt) that contains a number of quotations.

Perform the following steps to test QuoteClientApplet.

1. Download and save the following files to your local machine.

- QuoteClientApplet
- QuoteServer.java
- QuoteServerThread.java
- one-liners.txt
- quoteApplet.html

2. Include the following HTML code in a web page to deploy QuoteClientApplet.

<script src=
  "https://www.java.com/js/deployJava.js"></script>
<script>
    var attributes =
      { code:'QuoteClientApplet.class',  width:500, height:100} ;
    var parameters =
      { codebase_lookup:'true', permissions:'sandbox' };
    deployJava.runApplet(attributes, parameters, '1.6');
</script>

Alternatively, you can use the quoteApplet.html page that already contains this HTML code.

3. Compile the QuoteClientApplet.java class. Copy the generated class files to the same directory where you saved your web page.

4. Compile the classes for the server-side application, QuoteServer.java and QuoteServerThread.java.

5. Copy the file one-liners.txt to the directory that has the class files for the server-side application (generated in the previous step).

6. Start the server-side application.

java QuoteServer

You should see a message with the port number, as shown in the following example. Note the port number.

QuoteServer listening on port:3862

7. Open the web page containing your applet in a browser by entering the URL of the web page. The host name in the URL should be the same as the name of the host on which the server-side application is running.

For example, if the server-side application is running on a machine named JohnDoeMachine, you should enter a similar URL. The exact port number and path will vary depending on your web server setup.

http://JohnDoeMachine:8080/quoteApplet/quoteApplet.html

The QuoteClientApplet will be displayed on the web page.

8. Enter the port number of your server-side application in the applet's text field and click OK. A quotation is displayed.

Here is a screen capture of the applet in action.


QuoteServer Sample Output

What Applets Can and Cannot Do

Java applets are loaded on a client when the user visits a page containing an applet. The security model behind Java applets has been designed with the goal of protecting the user from malicious applets.

Applets are either sandbox applets or privileged applets. Sandbox applets are run in a security sandbox that allows only a set of safe operations. Privileged applets can run outside the security sandbox and have extensive capabilities to access the client.

Applets that are not signed are restricted to the security sandbox, and run only if the user accepts the applet. Applets that are signed by a certificate from a recognized certificate authority can either run only in the sandbox, or can request permission to run outside the sandbox. In either case, the user must accept the applet's security certificate, otherwise the applet is blocked from running.

It is recommended that you launch your applet using Java Network Launch Protocol (JNLP) to leverage expanded capabilities and improve user experience. See Deploying an Applet for step by step instructions on applet deployment.

It is recommended that you deploy your applets to a web server, even for testing. To run applets locally, add the applets to the exception site list, which is managed from the Security tab of the Java Control Panel.

In this topic we will discuss the security restrictions and capabilities of applets.

Sandbox Applets

Sandbox applets are restricted to the security sandbox and can perform the following operations:

◉ They can make network connections to the host and port they came from. Protocols must match, and if a domain name is used to load the applet, the domain name must be used to connect back to the host, not the IP address.
◉ They can easily display HTML documents using the showDocument method of the java.applet.AppletContext class.
◉ They 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.
◉ They can read secure system properties. 
◉ When launched by using JNLP, sandbox applets can also perform the following operations:
     ◉ They can open, read, and save files on the client.
     ◉ They can access the shared system-wide clipboard.
     ◉ They can access printing functions.
     ◉ They can store data on the client, decide how applets should be downloaded and cached, and much more. 

Sandbox applets cannot perform the following operations:

◉ They cannot access client resources such as the local filesystem, executable files, system clipboard, and printers.
◉ They cannot connect to or retrieve resources from any third party server (any server other than the server it originated from).
◉ They cannot load native libraries.
◉ They cannot change the SecurityManager.
◉ They cannot create a ClassLoader.
◉ They cannot read certain system properties. See System Properties for a list of forbidden system properties.

Privileged applets

Privileged applets do not have the security restrictions that are imposed on sandbox applets and can run outside the security sandbox.

Note: JavaScript code is treated like unsigned code. When a privileged applet is accessed from JavaScript code in an HTML page, the applet is executed within the security sandbox. This implies that the privileged applet essentially behaves likes a sandbox applet.

Solving Common Applet Problems

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

Problem: My applet does not display.

◉ Check the Java Console log for errors.
◉ Check the syntax of the applet's Java Network Launch Protocol (JNLP) file. Incorrect JNLP files are the most common reason for failures without obvious errors.
◉ Check the JavaScript syntax if deploying using the runApplet function of the Deployment Toolkit. See Deploying an Applet for details.

Problem: The Java Console log displays java.lang.ClassNotFoundException.

◉ Make sure your Java source files compiled correctly.
◉ If deploying using the <applet> tag, check that the path to the applet JAR file is specified accurately in the archive attribute.
◉ If launching using a JNLP file, check the path in the jar tag in the JNLP file.
◉ Make sure the applet's JAR file, JNLP file, and web page are located in the correct directory and reference each other accurately.

Problem: I was able to build the code once, but now the build fails even though there are no compilation errors.

◉ Close your browser and run the build again. The browser most likely has a lock on the JAR file, because of which the build process is unable to regenerate the JAR file.

Problem: When I try to load a web page that has an applet, my browser redirects me to www.java.com without any warning

◉ The applet on the web page is most likely deployed using the Deployment Toolkit script. The applet may require a later version of the Java Runtime Environment software than the version that currently exists on the client. Check the minimumVersion parameter of the runApplet function in the applet's web page. See Deploying an Applet for details.

Problem: I fixed some bugs and re-built my applet's source code. When I reload the applet's web page, my fixes are not showing up.

◉ You may be viewing a previously cached version of the applet. Close the browser. Open the Java Control Panel and delete temporary internet files. This will remove your applet from cache. Try viewing your applet again.

Questions and Exercises: Applets


Questions

1. Which classes can an applet extend?

2. For what do you use the start() method?

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

4. How do you get the value of a parameter specified in the JNLP file from within the applet's code?

5. Which class enables applets to interact with JavaScript code in the applet's web page?

6. True or False: Applets can modify the contents of the parent web page.

Exercises

1. The Exercise applet's parent web page has a JavaScript variable called memberId. Write the code to set the value of the memberId equal to "123489" in the applet's start method.

Answers to Questions and Exercises: Applets

Questions

1. Question: Which classes can an applet extend?

Answer: An applet can extend the java.applet.Applet class or the java.swing.JApplet class.

The java.applet.Applet class extends the java.awt.Panel class and enables you to use the GUI tools in the AWT package.

The java.swing.JApplet class is a subclass of java.applet.Applet that also enables you to use the Swing GUI tools.

2. Question: For what do you use the start() method?

Answer: You use the start() method when the applet must perform a task after it is initialized, before receiving user input. The start() method either performs the applet's work or (more likely) starts up one or more threads to perform the work.

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

Answer: False: An applet can only connect to the host that it came from.

4. Question: How do you get the value of a parameter specified in the JNLP file from within the applet's code?

Answer: You use the getParameter("Parameter name") method, which returns the String value of the parameter.

5. Question: Which class enables applets to interact with JavaScript code in the applet's web page?

Answer: The netscape.javascript.JSObject class enables applets to interact with JavaScript code in the applet's web page.

6. Question: True or False: Applets can modify the contents of the parent web page.

Answer: True:Applets can modify the contents of the parent web page by using the getDocument method of the com.sun.java.browser.plugin2.DOM class and the Common DOM API.

Exercises

1. Exercise: The Exercise applet's parent web page has a JavaScript variable called memberId. Write the code to set the value of the memberId equal to "123489" in the applet's start method.

Answer:

import java.applet.Applet;
import netscape.javascript.*; // add plugin.jar to
                              // classpath during
                              // compilation

public class Exercise extends Applet {
    public void start() {
        try {
            JSObject window =
                JSObject.getWindow(this);
            window.setMember("memberId", "123489");
        } catch (JSException jse) {
            jse.printStackTrace();
        }
    }
}

«« Previous
Next »»

0 comments:

Post a Comment