Previous Page TOC Next Page See Page



- 15 -
Communicating with Java Applets


Now that you've looked at the basics of creating Java Applets, it's time to examine the relationship between JavaScript and Java and methods of integrating Java Applets into Web pages using JavaScript.

Navigator 3 provides LiveConnect, a mechanism for communicating between JavaScript, Java applets, and plug-ins in a Web page. By using LiveConnect, it's possible to control applets and plug-ins from JavaScript, access JavaScript from applets, and more.

JavaScript provides the glue between applets and plug-ins and the rest of a Web page environment including forms, links and images. JavaScript also can be used as a middle layer for communication between applets and plug-ins.

This chapter takes a closer look at the role of JavaScript as the Java glue including the following topics:


When to Use Java and When to Use JavaScript


As mentioned in the preceding section, Java and JavaScript have distinct but complementary roles to play in the development of interactive Web pages. By effectively combining these two tools it is possible to enhance the usefulness of both.

For instance, traditionally, an applet may have produced a continuous text ticker-tape across a portion of the screen. Unless the applet itself provided mechanisms for the user to set properties of the ticker-tape, it wasn't possible for a Web author to add controls to the Java Applet without rewriting and compiling from the original source code of the applet.

With JavaScript, scripts can be designed to talk to the applet and effectively extend interactivity beyond the bounds of an applet's own defined interface to the whole Web page.



The ability for JavaScript and Java to communicate with each other has only been introduced with the beta releases of Navigator 3. Netscape Navigator 2.0 and it's sub-releases (2.01 and 2.02) do not support this ability.

The Java Developer's Kit includes the Blink applet, which simply takes a string and blinks it in random colors. Throughout this chapter, this applet is used to demonstrate all of the possibilities for JavaScript-Java communication.

The Blink applet takes two parameters: lbl (which represents the text to display) and speed. For example, the HTML code

<applet code="Blink.class" width=100 height=35>
<parameter name="lbl" value="Blink">
<parameter name="speed" value="4">
</applet>

produces results similar to those shown in Figure 15.1.

Figure 15.1 The Blink applet blinks a string of text in random colors.

By using JavaScript it's possible to add a form to the Web page that enables the user to start or stop the blinking (as shown in Figure 15.2.)

Figure 15.2. JavaScript can be used to control aspects of an applet.

When to Use Java


Being able to interact between Java and JavaScript is not enough. It is important to use the right tool for the right occasion.

Java is ideally suited to particular tasks, including the following:

Beyond these roles, Java also can be used when the programmer doesn't want to be tied to only JavaScript-capable platforms—even though the task could ably be performed by JavaScript. Presently, JavaScript is available on a more limited set of platforms than Java which is supported by more browsers than JavaScript and on dedicated devices such as Java-enabled X-terminals and network computers.

When to Use JavaScript


By comparison, JavaScript is suited to adding interactivity to elements of a Web page, including links, forms, images, applets and plug-ins.

JavaScript, because it includes objects and methods to address most elements making up an HTML document, can be used for the following:


The applet Object


Applets are accessible in JavaScript through an array of applet objects called applets. The applets array is a property of the document object. Applets are ordered in the array in the order they appear in the HTML source code—and as would be expected, are indexed starting at zero.



Throughout this chapter the interaction between Java and JavaScript is discussed. For the examples to work, it is important for both Java and JavaScript to be enabled in the network preferences dialog box, which is accessed through Navigator's Options menu.

For example, document.applets[0] refers to the first applet in a document.

Like other arrays of this nature in JavaScript, such as the forms and frames arrays, individual applets can be referred to by name. If the Blink applet were included in an HTML document using the <APPLET> tag

<APPLET CODE="Blink.class" NAME="Blink" WIDTH=300 HEIGHT=100>

Then the corresponding applet object could be referred to by it's index number or with document.Blink.

Accessing Properties and Methods of an Applet


Each applet is reflected into one applet object. The applet object provides the means for accessing all public variables in an applet as well as properties and methods.

Properties and methods are reflected into JavaScript as properties and methods of the corresponding applet object.

In the Blink applet example introduced in the preceding section, inspection of the Java source code reveals that there are five public methods in the applet:

/*
 * Copyright  1994 Sun Microsystems, Inc. All Rights Reserved.
 */
import java.awt.*;
import java.util.StringTokenizer;
/**
 * I love blinking things.
 *
 * @author Arthur van Hoff
 */
public class Blink extends java.applet.Applet implements Runnable {
    Thread blinker;
    String lbl;
    Font font;
    int speed;
    public void init() {
    font = new java.awt.Font("TimesRoman", Font.PLAIN, 24);
    String att = getParameter("speed");
    speed = (att == null) ? 400 : (1000 / Integer.valueOf(att).intValue());
    att = getParameter("lbl");
    lbl = (att == null) ? "Blink" : att;
    }
    public void paint(Graphics g) {
    int x = 0, y = font.getSize(), space;
    int red = (int)(Math.random() * 50);
    int green = (int)(Math.random() * 50);
    int blue = (int)(Math.random() * 256);
    Dimension d = size();
    g.setColor(Color.black);
    g.setFont(font);
    FontMetrics fm = g.getFontMetrics();
    space = fm.stringWidth(" ");
    for (StringTokenizer t = new StringTokenizer(lbl) ; t.hasMoreTokens() ; ) {
        String word = t.nextToken();
        int w = fm.stringWidth(word) + space;
        if (x + w > d.width) {
        x = 0;
        y += font.getSize();
        }
        if (Math.random() < 0.5) {
        g.setColor(new java.awt.Color((red + y * 30) % 256, (green + x / 3) % 256, blue));
        } else {
        g.setColor(Color.lightGray);
        }
        g.drawString(word, x, y);
        x += w;
    }
    }
    public void start() {
    blinker = new Thread(this);
    blinker.start();
    }
    public void stop() {
    blinker.stop();
    }
    public void run() {
    while (true) {
    try {Thread.currentThread().sleep(speed);} catch (InterruptedException e){}
        repaint();
    }
    }
}

If this blink applet were included in an HTML document using the following HTML code

<applet code="Blink.class" name="Blink" width=300 height=100>
<param name=lbl value="This is the next best thing to sliced bread! Toast, toast, toast, butter, jam, toast, marmite, toast.">
<param name=speed value="4">
</applet>

then the various methods in the Java applet could be accessed in JavaScript as

document.blink.init()
document.blink.paint()
document.blink.start()
document.blink.stop()
document.blink.run()

By way of example, the example earlier in this chapter where a start and stop button are added to the Blink applet using JavaScript is achieved with the following source code:

<applet code="Blink.class" name="Blink" width=300 height=100>
<param name=lbl value="This is the next best thing to sliced bread! Toast, toast, toast, butter, jam, toast, marmite, toast.">
<param name=speed value="4">
</applet>
<HR>
<form>
<input type=button value="start" onClick="document.Blink.start()">
<input type=button value="stop" onClick="document.Blink.stop()">
</form>

Simple onClick event handlers in the button definitions call the start() and stop() methods of the applet using document.blink.start() and document.blink.stop().

The process can be carried a step further by using JavaScript to dynamically update the text displayed by the applet. To do this requires one change to the Java applet's source code: the lbl variable needs to be declared as a public variable so that it is accessible in JavaScript:

public String lbl;

Once this changes is made and the applet is recompiled, then the HTML file's source code can be extended:

<applet code="Blink.class" name="Blink" width=300 height=100>

<param name=lbl value="This is the next best thing to sliced bread!  Toast, toast, toast, butter, jam, toast, marmite, toast.">
<param name=speed value="4">
</applet>
<HR>
<form>
<input type=text name="label"value="Enter Text Here">
<input type=button value="Change Text" onClick="document.Blink.lbl = this.form.label.value"><br>
<input type=button value="start" onClick="document.Blink.start()">
<input type=button value="stop" onClick="document.Blink.stop()">
</form>

Figure 15.3. By using JavaScript, it is possible to update the value of properties in an applet.

Here, the user enters text in the text field. When the new button is clicked, the value of the text field is assigned to document.Blink.lbl. When the applet next repaints the display, the new text is displayed by the applet.

Accessing Java Classes and Packages


Navigator 3 provides more than just the ability to access variables, properties, and methods in a Java applet. It's possible, using JavaScript, to access any class in the Java package name space.

Java's objects are organized into classes, which are collections of objects. Classes are organized into packages in which subclasses inherit the objects of their immediate parents (or superclasses) and then extend and change the class. Java has a substantial set of classes, all of which can be accessed in JavaScript.

The Java class hierarchy available in Navigator includes three packages: java, sun, and netscape, which provide different subclasses.



More information about the Java's native classes can be found at the JavaSoft home page: http://www.javasoft.com.

The JavaScript package name space is reflected in JavaScript under Packages. Thus, Packages.sun is the top of the java sun hierarchy. The java, sun, and netscape class hierarchies are also aliased in JavaScript to simply java, sun, and netscape.

Any Java class can be reflected into a JavaScript variable using a simple var statement. For instance,

var javaSystem = java.lang.System;

Here, the variable javaSystem is defined to point to the Java class java.lang.System, which is part of the java package. As a result, it's possible to make calls directly to methods or access properties of the class. For instance, to print text in the Java console, the println() method could be used:

javaSystem.err.println("JavaScript can print here.");

In addition, constructor classes in Java can be used to create instances in JavaScript (as is done with the Array() and Date()). For instance, instead of using JavaScript's date constructor, the Java date constructor could be used:

var javaDate = new java.util.Date();

As a result, the methods of the Java date class are available in JavaScript.

By using the ability to directly access Java methods and properties in a JavaScript script, it's possible to perform many Java tasks, such as network access and window manipulation, directly from within a JavaScript script.

By way of illustration, the following script uses Java's AWT class, which handles graphics and windows tasks, to open an empty 300x200 pixel Java window:

<script language="JavaScript">
var awt = java.awt;
var javaWin = new awt.Frame("Java Window");
javaWin.setLayout(new awt.BorderLayout(10,20));
javaWin.resize(300,200);
javaWin.show();
</script>

First, a reference to the entire java.awt class is created. Then, an instance of the Frame() constructor class called javaWin is created. The methods of javaWin are used to define the widow's size and display it. Further calls to other methods could have caused buttons, fields or text, among other things, to be displayed in the window.

The results look like those shown in Figure 15.4.

Figure 15.4. It is possible to use Java classes in JavaScript.

Calling JavaScript from Java


Communication between JavaScript and Java is not a one-way street, however. Not only is it possible to access Java properties, methods and variables from within a JavaScript script, a Java applet is also capable of calling JavaScript methods and accessing the value of JavaScript properties.



In order for an applet to have access to JavaScript properties and methods, it is necessary to explicitly give the applet permission to do this in the <APPLET> tag. This is done with the MAYSCRIPT attribute of the <APPLET> tag: <APPLET CODE="className" WIDTH=width HEIGHT=height NAME="appletName" MAYSCRIPT>.

In order to call a JavaScript method from Java, it is necessary to import the relevant JavaScript package into the applet: netscape.javascript.*.

netscape.javascript.* defines the JSObject class and the JSException object. JavaScript objects are instances of the class netscape.javascript.JSObject.

Once the necessary package is imported, accessing a JavaScript method or property is a two-step process: First a handle to the JavaScript window needs to be created and then the method or property can be accessed.

Handles are created using the getWindow() method of the JSObject object usually in the applet's init() method:

public void init() {
   JSObject handleName = JSObject.getWindow(this);
}

Once the handle is created, the getMember() method of the JSObject object can be used to access objects and properties from JavaScript. In order to create a handle to an object which is not a top-level object in JavaScript, such as the text field document.formName.fieldName, the getMember() method can be used for each object in the tree:

public void init() {
   JSObject handleName = JSObject.getWindow(this);
   JSObject documentHandle = (JSObject) handleName.getMember("document");
   JSObject formHandle = (JSObject) documentHandle.getMember("formName");
   JSObject fieldHandle = (JSObject) formHandle.getMember("fieldName");
}

Once the handle to the desired object is created, it's possible to use the getMember() method to access the value of one of the object's properties. In the preceding example, the value property of the text field's object could be assigned to a Java variable called fieldValue with

String fieldValue = (String) fieldHandle.getMember("value");

In order to call a method in JavaScript, a handle to the relevant object needs to created, as previously outlined. Once this is done, the JSObject object has two methods for calling JavaScript methods:

eval("expression")—the eval() method evaluates the JavaScript expression expression.

For example, the following is a Java applet which simply calls the JavaScript alert() method:

import netscape.javascript.JSObject;
import.netscape.javascript.JSException;
public class jsAlert extends java.applet.Applet implements Runnable {
   JSObject windowObject;
   public void init() {
      windowObject = JSObject.getWindow(this);
   }
   public void start() {
      windowObject.eval("alert(\"Hello from Java!\");");
   }
   public void stop() {
   }
   public void paint() {
   }
   public void run() {
   }
}

Notice that the windowObject variable is declared outside any method so that it's available in all the methods of the applet. In the init() method the handle to the top-level window object is created and in the start() method the eval() method is used to call JavaScript's alert() method. Notice the use of the backslash to escape the quotation marks in the call to the alert() method.

The results look like those shown Figure 15.5.

Figure 15.5. Using Java it is possible to call JavaScript methods.

The following script demonstrates how these techniques can be used to create a simple Java applet to display the value of a field in a form in the Java console.

import java.awt.*;
import java.util.StringTokenizer;
import netscape.javascript.JSObject;
import netscape.javascript.JSException;
public class twowayExample extends java.applet.Applet implements Runnable {
    String output;
    Font font;
    JSObject thiswindow;
    JSObject thisdocument;
    JSObject thisform;
    JSObject thisfield;
    public void init() {
    font = new java.awt.Font("TimesRoman", Font.PLAIN, 24);
    thiswindow = JSObject.getWindow(this);
    thisdocument = (JSObject) thiswindow.getMember("document");
    thisform = (JSObject) thisdocument.getMember("controlForm");
    thisfield = (JSObject) thisform.getMember("entryField");
    }
    public void run() {
    }
    public void displayField() {
       output = (String) thisfield.getMember("value");
       System.out.println(output);
    }
}

Figure 15.6. Java can react to changes in the value of a JavaScript property.

This applet assumes that it is being used in a page with a form called controlForm, with a text field called entryField. The applet initializes by reading the parameter output and setting up the font for output. Whenever the method displayField() is called, the output variable based on the content of the text field entryField and then this value is displayed in the Java console using System.out.println().

Using the netscape Package


All the applets in the previous section make use of a Java package called netscape.javascript. This package isn't one of the packages that make up the standard the class libraries available with the Java Developer's kit.

Instead, it is part of the class libraries which ship with Navigator 3. Navigator 3 comes with a file called moz3_0.zip, which includes all of the Java packages needed for Navigator to run. These include the netscape packages as well as versions of the standard java and sun packages, which enhance some of the security of these packages.



The file moz3_0.zip contains two packages, netscape.applet and netscape.net, which are replacements for the standard sun.applet and sun.net packages. Functionally these are the same as the original packages in the Java Developer's Kit.

In order to compile applets that use netscape.javascript (or netscape.plugins for communication between applets and plug-ins) it's necessary for the javac compiler to know where to find moz3_0.zip.

This is done by setting the CLASSPATH environment variable to specify the path and file name for both moz3_0.zip and classes.zip, which is part of the Java Developer's Kit. On Windows-based systems, this path would look something like the following:

C:\java\lib\classes.zip;c:\Navigator\Program\java\classes\moz3_0.zip

On Window systems, the CLASSPATH environment variable can be created in the System Control Panel applet. On UNIX systems, use the setenv command or the corresponding command in your shell.

Once the CLASSPATH environment variable is properly set, the javac compiler should be able to import netscape.javascript and the other packages in moz3_0.zip.

Summary


Starting with Navigator 3, JavaScript fulfills its promise as the tool to glue Java applets into Web pages. Using LiveConnect, it's possible for JavaScript to pass information to Java applets, access its properties, and invoke its methods, as well as have full access to Java packages and classes.

This communication is two-way. It is also possible for Java applets to access JavaScript objects and their properties and methods. As you'll see in later chapters, LiveConnect also provides methods for Java and JavaScript to communicate with Navigator plug-ins.

Previous Page Page Top TOC Next Page See Page