5.1 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.

Note:  Please make sure you have at least Java SE Development Kit (JDK) 6 update 10 release on your client machine before proceeding further. You will need this to view the sample rich internet applications and read subsequent sections without interruptions.

1. 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. See How to Use Root Panes for more details on how to use this feature.

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

2. 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.

3. 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. See the following topics to find out more about interactions between Java code and JavaScript code:

4. 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".


5. 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.


6. 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.

Developing and Deploying Java Applets

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");

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

8. 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

Open AppletPage.html in a browser to view the Data Summary applet .

Note:  If you don't see the applet running, you need to install at least the Java SE Development Kit (JDK) 6 update 10 release.

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.

9. 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. See JAR File Manifest Attributes for Security for information about the Caller-Allowable-Codebase attribute.

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.

10. 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 applet running, you need to install at least the Java SE Development Kit (JDK) 6 update 10 release.

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.

11. 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.

Note:  If you don't see the applet running, you need to install at least the Java SE Development Kit (JDK) 7 release.

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.


12. 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.

Note:  If you don't see the applet running, you need to install at least the Java SE Development Kit (JDK) 6 update 10 release.

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.

13. 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. View the IntegratedProgressIndicator.java class and the inline comments for more information.

14. 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.

15. 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 applet running, you need to install at least the Java SE Development Kit (JDK) 6 update 10 release.

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>

16. 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.

17. 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. Save the following files to your local machine.
  • QuoteClientApplet

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class QuoteClientApplet extends JApplet
                               implements ActionListener {
    private static boolean DEBUG = false;
    private InetAddress address;
    private JTextField portField;
    private JLabel display;
    private JButton sendButton;
    private JProgressBar progressBar;
    private DatagramSocket socket;
    private String host;
    private static final int MAX_NUM_CHARS = 256;
    private static final int TIMEOUT = 500; //time out after 1/2 a second
    private static String sendButtonText = "OK";
    private QuoteGetter quoteGetter;
    public void init() {
        //Initialize networking stuff.
        host = getCodeBase().getHost();
        try {
            address = InetAddress.getByName(host);
        } catch (UnknownHostException e) {
            System.err.println("Couldn't get Internet address: Unknown host");
            // What should we do?
        }
        try {
            socket = new DatagramSocket();
            socket.setSoTimeout(TIMEOUT);
        } catch (IOException e) {
            System.err.println("Couldn't create new DatagramSocket");
            return;
        }
        //Set up the UI.
        //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");
        }
    }
    private void createGUI() {
        JPanel contentPane = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        int numColumns = 3;
        JLabel l1 = new JLabel("Quote of the Moment:", JLabel.CENTER);
        c.gridx = 0;
        c.gridy = 0;
        c.anchor = GridBagConstraints.SOUTH;
        c.gridwidth = numColumns;
        contentPane.add(l1, c);
        display = new JLabel("(no quote received yet)", JLabel.CENTER);
        display.setForeground(Color.gray);
        c.gridy = 1;
        c.gridwidth = numColumns;
        c.anchor = GridBagConstraints.CENTER;
        c.weighty = 1.0;
        c.fill = GridBagConstraints.HORIZONTAL;
        contentPane.add(display, c);
        JLabel l2 = new JLabel("Enter the port (on host " + host
                               + ") to send the request to:",
                               JLabel.RIGHT);
        c.gridy = 2;
        c.gridwidth = 1;
        c.anchor = GridBagConstraints.SOUTH;
        c.weighty = 0.0;
        c.fill = GridBagConstraints.NONE;
        contentPane.add(l2, c);
        portField = new JTextField(6);
        c.gridx = 1;
        c.weightx = 1.0;
        c.insets = new Insets(0,5,0,0);
        c.fill = GridBagConstraints.HORIZONTAL;
        contentPane.add(portField, c);
        sendButton = new JButton(sendButtonText);
        c.gridx = 2;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.NONE;
        contentPane.add(sendButton, c);
        progressBar = new JProgressBar();
        c.gridx = 0;
        c.gridy = 3;
        c.gridwidth = numColumns;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(5,0,5,0);
        contentPane.add(progressBar, c);
        portField.addActionListener(this);
        sendButton.addActionListener(this);
        //Finish setting up the content pane and its border.
        contentPane.setBorder(BorderFactory.createCompoundBorder(
                                    BorderFactory.createLineBorder(Color.black),
                                    BorderFactory.createEmptyBorder(5,20,5,10)));
        setContentPane(contentPane);
    }
    private class QuoteGetter extends SwingWorker<String, String> {
        int port;
        InetAddress address;
        public QuoteGetter(int port, InetAddress address) {
            this.port = port;
            this.address = address;
        }
         @Override
         public String doInBackground() {
            DatagramPacket packet;
            byte[] sendBuf = new byte[MAX_NUM_CHARS];
            packet = new DatagramPacket(sendBuf, MAX_NUM_CHARS, address, port);
            try { // send request
                if (DEBUG) {
                    System.out.println("Applet about to send packet to address "
                                   + address + " at port " + port);
                }
                socket.send(packet);
                if (DEBUG) {
                    System.out.println("Applet sent packet.");
                }
            } catch (IOException e) {
                System.err.println("Applet socket.send failed:\n"
                                   + e.getStackTrace());
                return null;
            }
            packet = new DatagramPacket(sendBuf, MAX_NUM_CHARS);
            try { // get response
                if (DEBUG) {
                    System.out.println("Applet about to call socket.receive().");
                }
                socket.receive(packet);
                if (DEBUG) {
                    System.out.println("Applet returned from socket.receive().");
                }
            } catch (SocketTimeoutException e) {
                System.err.println("Applet socket.receive timed out.");
                //Should let the user know in the UI.s
                return null;
            } catch (IOException e) {
                System.err.println("Applet socket.receive failed:\n"
                                   + e.getStackTrace());
                return null;
            }
            String received = new String(packet.getData());
            StringBuffer data = new StringBuffer(received);
            //Hack alert! Assuming the last character is garbage, rid
            //this string of all garbage characters.
            int firstGarbage = data.indexOf(Character.toString(
                                            received.charAt(MAX_NUM_CHARS - 1)));
            if (firstGarbage > -1) {
                data.delete(firstGarbage, MAX_NUM_CHARS);
            }
            return data.toString();
         }
        //Once the socket has been read, display what it sent.
        protected void done() {
            if (DEBUG) {
                System.out.println("SwingWorker is done.");
            }
            progressBar.setIndeterminate(false);
            try {
                String s = get();
                if (DEBUG) {
                    System.out.println("get() returned \"" + s + "\"");
                }
                if (s != null) {
                    //Display the text.
                    display.setForeground(Color.gray);
                    display.setText(s);
                } else {
                    display.setForeground(Color.red);
                    display.setText("Read failed (see console for details).");
                }
            } catch (Exception ignore) { }
         }
    }
    //invoked on the event-dispatching thread
    private void doIt(int port) {
        //Listen to the port on a background thread to avoid
        //tying up the GUI.
        quoteGetter = new QuoteGetter(port, address);
        quoteGetter.execute();
        display.setForeground(Color.gray);
        display.setText("Reading port #" + port);
    }
    public void actionPerformed(ActionEvent event) {
        try {
            int port = Integer.parseInt(portField.getText());
            progressBar.setIndeterminate(true);
            doIt(port);
        } catch (NumberFormatException e) {
            //No integer entered.
            display.setForeground(Color.red);
            display.setText("Please enter a number in the text field below.");
        }
    }
    public void destroy() {
        //destroy the DatagramSocket?
        if (socket != null) {
            socket.close();
        }
        //Set up the UI.
        //Execute a job on the event-dispatching thread:
        //creating this applet's GUI.
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    getContentPane().removeAll();
                }
            });
        } catch (Exception e) { }
    }
}
  • QuoteServer.java

class QuoteServer {
    public static void main(String[] args) {
        new QuoteServerThread().start();
    }
}
  • QuoteServerThread.java

import java.io.*;
import java.net.*;
import java.util.*;
class QuoteServerThread extends Thread {
    private DatagramSocket socket = null;
    BufferedReader qfs = null;
    private boolean moreQuotes = true;
    private int bufLength = 256;
    QuoteServerThread() {
        super("QuoteServer");
        try {
            socket = new DatagramSocket();
            System.out.println("QuoteServer listening on port: " + socket.getLocalPort());
        } catch (java.io.IOException e) {
            System.err.println("Could not create datagram socket.");
        }
        this.openInputFile();
    }
    public void run() {
        if (socket == null)
            return;
        while (moreQuotes) {
            try {
                byte[] buf = new byte[bufLength];
                DatagramPacket packet;
                InetAddress address;
                int port;
                String dString = null;
                    // receive request
                packet = new DatagramPacket(buf, bufLength);
                socket.receive(packet);
                address = packet.getAddress();
                port = packet.getPort();
                    // send response
                if (qfs == null)
                    dString = new Date().toString();
                else
                    dString = getNextQuote();
                buf = dString.getBytes();
                packet = new DatagramPacket(buf, buf.length, address, port);                
                socket.send(packet);
            } catch (IOException e) {
                System.err.println("IOException:  " + e);
                moreQuotes = false;
                e.printStackTrace();
            }
        }
        socket.close();
    }
    private void openInputFile() {
        try {
            qfs = new BufferedReader(new FileReader("one-liners.txt"));
        } catch (java.io.FileNotFoundException e) {
            System.err.println("Could not open quote file. Serving time instead.");
        }
    }
    private String getNextQuote() {
        String returnValue = null;
        try {
            if ((returnValue = qfs.readLine()) == null) {
                qfs.close();
                moreQuotes = false;
                returnValue = "No more quotes. Goodbye.";
            }           
        } catch (IOException e) {
            returnValue = "IOException occurred in server.";
        }
        return returnValue;
    }
}
  • one-liners.txt

Life is wonderful. Without it we'd all be dead.
Daddy, why doesn't this magnet pick up this floppy disk?
Give me ambiguity or give me something else.
I.R.S.: We've got what it takes to take what you've got!
We are born naked, wet and hungry. Then things get worse.
Make it idiot proof and someone will make a better idiot.
He who laughs last thinks slowest!
Always remember you're unique, just like everyone else.
"More hay, Trigger?" "No thanks, Roy, I'm stuffed!"
A flashlight is a case for holding dead batteries.
Lottery: A tax on people who are bad at math.
Error, no keyboard - press F1 to continue.
There's too much blood in my caffeine system.
Artificial Intelligence usually beats real stupidity.
Hard work has a future payoff. Laziness pays off now.
"Very funny, Scotty. Now beam down my clothes."
Puritanism: The haunting fear that someone, somewhere may be happy.
Consciousness: that annoying time between naps.
Don't take life too seriously, you won't get out alive.
I don't suffer from insanity. I enjoy every minute of it.
Better to understand a little than to misunderstand a lot.
The gene pool could use a little chlorine.
When there's a will, I want to be in it.
Okay, who put a "stop payment" on my reality check?
We have enough youth, how about a fountain of SMART?
Programming is an art form that fights back.
"Daddy, what does FORMATTING DRIVE C mean?"
All wiyht. Rho sritched mg kegtops awound?
My mail reader can beat up your mail reader.
Never forget: 2 + 2 = 5 for extremely large values of 2.
Nobody has ever, ever, EVER learned all of WordPerfect.
To define recursion, we must first define recursion.
Good programming is 99% sweat and 1% coffee.
Home is where you hang your @
The E-mail of the species is more deadly than the mail.
A journey of a thousand sites begins with a single click.
You can't teach a new mouse old clicks.
Great groups from little icons grow.
Speak softly and carry a cellular phone.
C:\ is the root of all directories.
Don't put all your hypes in one home page.
Pentium wise; pen and paper foolish.
The modem is the message.
Too many clicks spoil the browse.
The geek shall inherit the earth.
A chat has nine lives.
Don't byte off more than you can view.
Fax is stranger than fiction.
What boots up must come down.
Windows will never cease.   (ed. oh sure...)
In Gates we trust.    (ed.  yeah right....)
Virtual reality is its own reward.
Modulation in all things.
A user and his leisure time are soon parted.
There's no place like http://www.home.com
Know what to expect before you connect.
Oh, what a tangled website we weave when first we practice.
Speed thrills.
Give a man a fish and you feed him for a day; teach him to use the Net and he won't bother you for weeks.
  • 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.

Developing and Deploying Java Applets
QuoteServer Sample Output

18. 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. See System Properties for a list of 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. See JNLP API for more information about developing applets by using the JNLP API.
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. 

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.

19. 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.


20. 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 »»