Talk with me Java

Get your JavaScript code and Java applets communicating with each other

Some day your boss may ask you to integrate a Java applet with some JavaScript code. How would you accomplish that task? For starters, you should know the basics of communication between JavaScript and Java. This article examines those basics. It first investigates how JavaScript code talks to a Java applet and then looks at the reverse scenario: the applet talking to JavaScript code.

Note: I created and tested this article's code using version 1.4.1_05 of Sun's Java 2 SDK, the Java plug-in for that version's associated Java Runtime Environment, the Internet Explorer 5.50.4134.0100 Web browser, and the Netscape Navigator 6.2.3 Web browser. The underlying platform for all that software was Microsoft Windows ME.

JavaScript calling Java

Modern Web browsers use the document object model (DOM) to expose a Webpage's elements as programmable components, with their own sets of properties and methods. DOM exposes the current Webpage via the document object and—via the id or name attributes—treats named applet, form, and other HTML elements as document's properties. For example, suppose that you specify the following applet element in an HTML file:

 <applet code="Calculator.class" name="Calc" width=200 height=200>
</applet>

According to DOM, Calc is a property of Document, and document.Calc refers to that property. If the applet exposes any public fields or methods, JavaScript can access them through DOM. For example, assume Calculator exposes method public void clear() and field public String value. In JavaScript, access both members via document.Calc.clear (); and document.Calc.value.

Let's put this knowledge to good use. Listing 1's JSTOJ.html text specifies applet JSTOJ, form JSTOJForm, and a pair of JavaScript functions. The callJava() function updates the applet's displayed message and background color when either the form's text-field content changes (and focus leaves the field) or a selection is made from the drop-down list of color names:

Listing 1. JSTOJ.html

 <html>
  <head>
    <title>JavaScript To Java</title>
    <script language="JavaScript1.3">
      var JSTOJForm;
      function init ()
      {
         JSTOJForm = document.JSTOJForm;
      }
      function callJava ()
      { 
         document.JSTOJ.msg = JSTOJForm.msg.value;
         document.JSTOJ.setColor (JSTOJForm.colors.options
                                  [JSTOJForm.colors.selectedIndex].value);
      }
    </script>
  </head>
  <body onload="init ()">
    <applet code="JSTOJ.class" name="JSTOJ" width=300 height=300>
    </applet>
    <p>
    <form name="JSTOJForm">
      <input name="msg" type="text" size="30" onchange="callJava ()">
      <select name="colors" size="1" onchange="callJava ()">
        <option value="black" selected>black</option>
        <option value="red">red</option>
        <option value="magenta">magenta</option>
        <option value="blue">blue</option>
      </select>
    </form>
  </body>
</html>

When either of the onchange or onload event handlers invokes callJava(), JSTOJForm.msg.value returns the text content of the form's msg text field, which is assigned to the document.JSTOJ applet's public msg field. Similarly, JSTOJForm.colors.options [JSTOJForm.colors.selectedIndex].value returns the selected text content of the form's colors drop-down list field, which passes as an argument to the applet's public setColor() method. Listing 2 presents that applet's source code:

Listing 2. JSTOJ.java

 // JSTOJ.java
// This program constructs an applet with A GUI and all necessary logic for
// displaying a message on a colored background.
import java.awt.*;
import java.applet.Applet;
// ==========================================================================
// Class: JSTOJ
//
// This class is the main (and only) class for the JSTOJ applet. Even though
// field msg and methods init(), paint(), and setColor() are all public, only
// msg and setColor() should be accessed from JavaScript.
// ==========================================================================
public class JSTOJ extends Applet
{
   // The following variable identifies the message to be displayed.
   public String msg = System.getProperty ("java.version"); 
   // ==================================================================
   // Method: init()
   //
   // Initialize the applet by drawing msg's text on a black background.
   //
   // Arguments:
   // 
   // none
   //
   // Return:
   //
   // nothing
   // ==================================================================
   public void init ()
   {
      setColor ("black");
   }
   // ===================================
   // Method: paint()
   //
   // Paint the applet's drawing surface.
   //
   // Arguments:
   // 
   // g - graphics context
   //
   // Return:
   //
   // nothing
   // ===================================
   public void paint (Graphics g)
   {
      // Obtain the width and height of the applet's drawing surface.
      int w = getSize ().width;
      int h = getSize ().height;
      // Paint applet's drawing surface using current foreground color.
      g.fillRect (0, 0, w, h);
      // Calculate the coordinates of the text baseline so that the message
      // appears centered when drawn.
      FontMetrics fm = g.getFontMetrics ();
      int x = (w - fm.stringWidth (msg)) / 2;
      int y = (h - fm.getHeight ()) / 2;
      // Change the foreground color to white and draw the message in this
      // color.
      g.setColor (Color.white);
      g.drawString (msg, x, y);
   }
   // ====================================================================
   // Method: setColor()
   //
   // Set the applet's foreground drawing color and call repaint() to 
   // indirectly paint its drawing surface.
   //
   // Arguments:
   // 
   // color - name of foreground color (must be red, green, blue or black)
   //
   // Return:
   //
   // nothing
   // ====================================================================
   public void setColor (String color)
   {
      if (color.equals ("red"))
          setForeground (Color.red);
      else
      if (color.equals ("magenta"))
          setForeground (Color.magenta);
      else
      if (color.equals ("blue"))
          setForeground (Color.blue);
      else
          setForeground (Color.black);
      repaint ();
   }
}

The Java source code is straightforward. It initializes the applet to reveal a drawing surface with a white and centered Java version-number text on a black background. Subsequent calls to setColor() change the drawing surface color and then repaint that surface. If msg's content changes prior to a setColor() call, the new content displays over a background painted in the new drawing surface color.

Compile JSTOJ.java and load JSTOJ.html into Internet Explorer. (For some reason, it is not possible to modify a public field under Netscape Navigator. However, it is possible to modify the field under Internet Explorer. That is why Internet Explorer is used in this experiment.) Type some text into the form's text field and then select a color. Figure 1 reveals one possible result.

Figure 1. JavaScript calling Java on a blue background

Java calling JavaScript

DOM lets JavaScript code access a Java applet's public fields and methods. How do we accomplish the reverse—allow a Java applet to access JavaScript code? Netscape provides a solution: netscape.javascript. That package's two classes make reverse communication possible: JSObject and JSException (which subclasses RuntimeException).

JSObject presents nine methods, with public static JSObject getWindow (Applet applet) being the most important. When called with a this reference to the current applet, getWindow() returns a reference to a JSObject, whose methods allow the applet to access JavaScript code associated with the applet's window (the document in which the applet element resides). The following line of code demonstrates that: JSObject window = JSObject.getWindow (this);.

Once you have a JSObject reference, you can execute any method in the following table:

JSObject Methods

Method Name Prototype Description
call public Object call (String methodName, Object [] args) Call a JavaScript method. methodName provides the method's name and args provides an array of arguments to pass to the method. Pass null if the method takes no arguments.
eval public Object eval (String s) Evaluate a JavaScript expression.
getMember public Object getMember (String name) Retrieve the named member of a JavaScript object. Equivalent to this.name in JavaScript.
getSlot public Object getSlot (int index) Retrieve the indexed member of a JavaScript object. Equivalent to this[index] in JavaScript.
removeMember public void removeMember (String name) Remove a named member from a JavaScript object.
setMember public void setMember (String name, Object value) Set a named member in a JavaScript object. Equivalent to this.name = value.
setSlot public void setSlot (int index, Object value) Set an indexed member in a JavaScript object. Equivalent to this[index] = value.
toString public String toString () Return this JSObject's string representation.

Most of the table's methods and getWindow() are capable of throwing JSException objects. For example, passing null to getWindow() results in a thrown JSException object for both Internet Explorer and Netscape Navigator. Another example: specifying a nonexistent method name as an argument to call(). However, only Internet Explorer throws a JSException object in that situation. Netscape Navigator simply returns execution from call(), with no acknowledgement of the nonexistent method.

Let's play with JSObject. Listing 3's JTOJS.html text specifies applet JTOJS, form JTOJSForm, and one JavaScript function: callFromJava(). That function updates the form's text field content with the content from argument msg when called from Java:

Listing 3. JTOJS.html

 <html>
  <head>
    <title>Java To JavaScript</title>
    <script language="JavaScript1.3">
      function callFromJava (msg)
      {
         document.JTOJSForm.msg.value = msg;
      }
    </script>
  </head>
  <body>
    <applet code="JTOJS.class" width=500 height=50 mayscript>
    </applet>
    <p>
    <form name="JTOJSForm">
      <input name="msg" type="text" size="30" value="Java output goes here">
    </form>
  </body>
</html>

Notice the <applet> tag's mayscript attribute? The purpose of that attribute: inform the browser if the Java applet can call out to JavaScript or access DOM. If mayscript isn't present, calls to JSObject methods might fail. Although Internet Explorer ignores mayscript, Netscape Navigator requires that attribute. Calls to JSObject methods cause JSException objects to be thrown if mayscript isn't present.

When the JTOJS applet invokes method callFromJava(), the msg argument's content is assigned to the msg text field in the JTOJSForm form. Listing 4 reveals that applet's source code:

Listing 4. JTOJS.java

 // JTOJS.java
// This program constructs an applet whose only purpose is to call the
// JavaScript script that contains a "callFromJava()" function.
import netscape.javascript.JSObject;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
// =============================================================
// Class: JTOJS
//
// This class is the main (and only) class for the JTOJS applet.
// =============================================================
public class JTOJS extends Applet
{
   // =============================================
   // Method: init()
   //
   // Initialize the applet by creating a simple GUI.
   //
   // Arguments:
   // 
   // none
   //
   // Return:
   //
   // nothing
   // =============================================
   public void init ()
   {
      // Set the background color to cyan, for aesthetic reasons.
      setBackground (Color.cyan);
      // Organize GUI components in a Panel.
      Panel p = new Panel ();
      // Create an informative Label.
      Label l = new Label ("Enter a message (and press Enter):");
      // Establish a matching background color for Label.
      l.setBackground (Color.cyan);
      // Add Label to Panel.
      p.add (l);
      // Create a TextField for data entry.
      final TextField t = new TextField (20);
      // Create action listener to respond to Enter being pressed. In
      // response, send contents of TextField to JavaScript.
      ActionListener al;
      al = new ActionListener ()
           {
               public void actionPerformed (ActionEvent e)
               {
                  // Prepare array of arguments for call to JavaScript.
                  Object [] args = { t.getText () };
                  // Obtain the browser window in which this applet is
                  // displayed.
                  JSObject window = JSObject.getWindow (JTOJS.this);
                  // Call the JavaScript "callFromJava()" function and pass
                  // args to this function.
                  window.call ("callFromJava", args);
               }
           };
      t.addActionListener (al);
      // Add TextField to Panel.
      p.add (t);
      // Add Panel to applet.
      add (p);
   }
}

1 2 Page
Recommended
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more