Plug into Java with Java Plug-in, Part 2

Use Java Plug-in with the Firefox Web browser

Six years have passed since I wrote "Plug into Java with Java Plug-in" for JavaWorld. My earlier article defined Java Plug-in, showed how to install version 1.2 for Netscape Communicator 4.5 and Internet Explorer 3.02, presented Windows registry settings related to Java Plug-in, explored Java Plug-in's control panel, examined two Java consoles, discussed the <embed> and <object> HTML tags, and revealed a Swing-based demonstration applet.

Many versions of Java and Java Plug-in have emerged since I wrote that article. And since it's showing its age, I've created a sequel that focuses on one of the more recent Java Plug-ins in the context of the Firefox Web browser. This article first shows you how to access Java Plug-in from Firefox. It next examines the Java Plug-in Document Object Model (DOM), applet state persistence, and cookies. Various applets, run from Firefox, reinforce the knowledge you acquire while studying those topics. The article concludes by exploring the link between Firefox and Java Plug-in. Because there is more to Java Plug-in than what I cover in this article, I recommend studying Sun's Java Plug-in documentation to learn more about that technology.

I base this article's material on Mozilla Firefox 1.0, J2SE 5.0, and Windows 98 SE. Even if you don't have this software, I still recommend reading the article. Hopefully, you will discover some interesting material that is new to you.

Java Plug-in and Firefox

Java Plug-in serves as a bridge between a browser and an external Java Runtime Environment (JRE). Java Plug-in is essential for running applets in Firefox because the browser doesn't provide a JRE—including a JVM—of its own. Because this article presents applets that demonstrate different Java Plug-in topics, and because I run these applets in a Firefox context, we should review how to access Java Plug-in from Firefox. For starters, make sure that J2SE 5.0 and JRE are installed on your platform. On my Windows platform, I installed both J2SE and JRE from the jdk-1_5_0-windows-i586.exe installation file. Make sure to include the JRE in the installation because the JRE includes Java Plug-in.

After installing J2SE 5.0, connect Firefox to Java Plug-in: first select Options from Firefox's Tools menu, next select Web Features, and finally check the Enable Java checkbox.

Traditionally, the <embed> and <object> tags had to be specified to run applets under Java Plug-in. This is not necessary with Java Plug-in 5.0, which can run applets specified by the simpler <applet> tag. During installation, you are given the opportunity to have the Internet Explorer and Mozilla (Firefox)/Netscape Web browsers hand off applet execution to Java Plug-in when they encounter the <applet> tag. If you forego this option, you can make the change later via the Java Plug-in control panel. For example, start the control panel and select the Advanced tab. Then click the plus sign to the left of <APPLET> Tag Support and check the box marked Mozilla and Netscape. Close the control panel and Firefox passes execution to Java Plug-in whenever it encounters the <applet> tag. Figure 1 reveals the needed change.

Figure 1. Check Mozilla and Netscape so Firefox can pass applet execution to Java Plug-in when it encounters the <applet> tag
Note
I've discovered that checking Mozilla and Netscape is not necessary on my platform. My Firefox Web browser passes execution to Java Plug-in when it encounters <applet>, regardless of that checkbox setting. The Java Plug-in 5.0 documentation has this to say about that strange behavior: "If Mozilla and Netscape 7 are both installed and <APPLET> tag support for Mozilla and Netscape is disabled (unchecked), <APPLET> tags continue to run with the Sun VM. This is a bug that is related to the autoscan feature of Netscape 7." Because I also have Netscape 6.2.3 installed, I suppose I've found that bug. Keep this in mind if you encounter similar behavior on your platform.

Platforms can host multiple JREs. Which JRE does Java Plug-in use when Firefox encounters an

<applet>

tag? Find the answer from the Java tab on Java Plug-in's control panel. Alternatively, my version-detection applet presents that answer and proves that Firefox is connected to Java Plug-in. Figure 2 reveals 1.5.0 to be the JRE version that I am using. (Version 1.5.0 is the internal version number for J2SE 5.0.)

Figure 2. I've configured Java Plug-in to use JRE 1.5.0

Listing 1 presents this applet's VersionDemo.java source code. The source code determines the JRE version from the java.version system property.

Listing 1. VersionDetect.java

 

// VersionDetect.java

import java.awt.*;

public class VersionDetect extends java.applet.Applet { public void paint (Graphics g) { int width = getSize ().width; int height = getSize ().height;

g.setColor (Color.orange); g.fillRect (0, 0, width, height);

String version = "JRE " + System.getProperty ("java.version");

FontMetrics fm = g.getFontMetrics ();

g.setColor (Color.black); g.drawString (version, (width-fm.stringWidth (version))/2, height/2); } }

For brevity, I don't show the HTML for running this or any other applet presented in this article. Consult the source code that accompanies this article for that HTML.

Note
Firefox only supports Java Plug-in 1.3.0_01 and higher.

Contact the DOM

According to the World Wide Web Consortium, the Document Object Model (DOM) is an API "for valid HTML and well-formed XML documents. It defines the logical structure of documents and the way a document is accessed and manipulated." Java Plug-in offers two ways to contact the DOM: the netscape.javascript.JSObject class and the Common DOM API.

The JSObject interfaces between a Java applet and a Web browser's JavaScript implementation, including JavaScript objects that expose the DOM. Examples of those objects: Document, Link, and Window. I won't delve into JSObject because I discussed that class in my earlier "Talk with Me Java" article. Rather, I focus on the Common DOM API for traversing the DOM from within an applet.

The Common DOM API, introduced in J2SE version 1.4, is a collection of classes and interfaces that lets applets traverse DOM instances. Because a browser can present multiple documents via frames and windows, many DOM instances (one per document) are available for traversal. An applet typically traverses its own DOM instance—the DOM instance associated with the document identifying the applet.

The starting point for accessing a DOM instance is the static getService(Object obj) method, which is located in the com.sun.java.browser.dom.DOMService class. Typically, an invoking applet's this reference passes as an argument to getService(). That method either returns a DOMService object that interfaces between the applet and its DOM instance or throws an exception: com.sun.java.browser.dom.DOMUnsupportedException (the DOM service is not available to the object) or com.sun.java.browser.dom.DOMAccessException (a security violation has resulted). Example: DOMService service = DOMService.getService (this);.

Because Web browsers provide different DOM implementations, access to a DOM instance is not thread safe, unless that access occurs on the DOM access dispatch thread. To ensure thread safety, DOMService provides two methods that guarantee access only on the DOM access dispatch thread—invokeLater() and invokeAndWait(). Either method takes a com.sun.java.browser.dom.DOMAction interface object argument that presents a run() method. invokeLater() executes run() asynchronously on the DOM access dispatch thread, whereas invokeAndWait() executes run() synchronously on the DOM access dispatch thread.

The run() method takes a com.sun.java.browser.dom.DOMAccessor interface object as its single argument and returns a generic Object. The run() method often invokes DOMAccessor's getDocument() method, passing a reference to the applet as getDocument()'s Object argument. In reply, getDocument() returns an org.w3c.dom.Document interface object. That object's methods return information about the document. For HTML documents, cast from Document to HTMLDocument (located in org.w3c.dom.html) and invoke HTMLDocument's methods to obtain the document's title, domain, collection of applets, and more. After invoking appropriate methods, run() returns documentation information (such as an HTML document's title) as an Object. That Object subsequently returns from the invokeLater() and invokeAndWait() methods.

To clarify the discussion above, I've created a title extraction applet that extracts the title from an HTML document and displays that title to the user. That applet's TitleExtract.java source code appears in Listing 2.

Listing 2. TitleExtract.java

 

// TitleExtract.java

import com.sun.java.browser.dom.*;

import java.applet.Applet;

import java.awt.*;

import org.w3c.dom.html.*;

public class TitleExtract extends Applet { private String title = "unknown";

public void init () { try { DOMService service = DOMService.getService (this); title = (String) service.invokeAndWait (new DOMAction () { public Object run (DOMAccessor accessor) { HTMLDocument doc = (HTMLDocument) accessor.getDocument (TitleExtract.this); return doc.getTitle (); } }); } catch (DOMUnsupportedException e) { System.out.println ("DOM not supported"); } catch (DOMAccessException e) { System.out.println ("DOM cannot be accessed"); } }

public void paint (Graphics g) { int width = getSize ().width; int height = getSize ().height;

g.setColor (Color.cyan); g.fillRect (0, 0, width, height);

FontMetrics fm = g.getFontMetrics ();

g.setColor (Color.black); g.drawString (title, (width-fm.stringWidth (title))/2, height/2); } }

The DOMAction's run() method invokes HTMLDocument's getTitle() method to obtain the HTML document's title. That title subsequently displays. For example, when presented with the <title>Extract the title</title> element (excerpted from TitleExtract.html—see this article's source code), getTitle() returns Extract the title. Firefox displays this title in Figure 3.

Figure 3. A document's title is exposed
Caution
Firefox requires that the mayscript attribute be present when invoking TitleExtract from the <applet> tag. Otherwise, due to the FireFox DOM implementation's reliance on JSObject, Java Plug-in throws various exceptions.

Persist applet state across Firefox sessions

The Java Plug-in 5.0 documentation presents many interesting topics. One topic of interest is the applet persistence API, which lets an applet save its state for future access in the same Web browser session. State is saved in an internal persistence-store datastructure managed by Java Plug-in; a session begins when the Web browser starts to run and ends when the browser terminates.

The applet persistence API, introduced in J2SE 1.4, consists of three methods declared in the java.applet.AppletContext interface:

  • void setStream(String key, InputStream stream) throws IOException associates a specific key with a specific stream in the current applet context. If a stream currently maps to the key, the new stream replaces the old stream. An IOException is thrown if the size of the new stream exceeds an internal size limit.
  • InputStream getStream(String key) returns the InputStream associated with the key in the current applet context. null returns if there is no mapping for the key.
  • Iterator<String> getStreamKeys() returns an Iterator over all keys mapped to streams in the current applet context.

Save state by calling setStream(). That method stores a key (that conveniently identifies an input stream) and an InputStream reference in an internal datastructure, such as a HashMap. Restore state by calling getStream() with the identical key. That method returns an InputStream (if the key exists) to recover the state.

Because the Java Plug-in 5.0 documentation offers no example on how to use the applet persistence API, I have prepared an example. This example presents two instances of a message transfer applet, with each using the applet persistence API to send messages to the other. In Figure 4, the user enters a message in the Message To Send text field of the left instance and clicks that instance's Send button. The user then clicks the right instance's Receive button and the message appears in that instance's Message Received text field.

Figure 4. The applet persistence API lets applets transfer messages to each other. Click on thumbnail to view full-sized image.

Listing 3 presents the message transfer applet's MessageTransfer.java source code. Message transfers occur in that source code's action listener.

Listing 3. MessageTransfer.java

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