BEAN CONNECT: USING JAVA OBJECTS TO IMPLEMENT CROSSWARE PROGRAMS


This is a preliminary document that describes the BeanConnect program model, a new, highly flexible model for providing Java-based crossware programs. BeanConnect programs can:

This document is divided into three sections. The first section provides a conceptual overview describing the benefits of the BeanConnect program model in detail. The second section describes the actual implementation of BeanConnect programs. It offers implementation information both for a simple BeanConnect program that uses Java components that are handled by JavaScript, and for a more complex BeanConnect program, implemented completely in Java, that spans frames on an HTML page. The final section of this document provides the complete code for the BeanConnect programs previously described in the document.

CONCEPTUAL OVERVIEW

Currently, developers who provide Java components and objects for crossware applications are mandated to use Applet and related classes in the Sun java.applet package to create an application, and must use the <APPLET> tag to embed the application in an HTML page. While the applet model works well for simple, self-contained Java applications, each such applet is restricted to a single AWT Frame object, runs in the page where it is embedded, and cannot participate in HTML form posting. The applet model does not provide a shared execution context for multiple objects. Finally, applet lifetime is not well-defined, and cannot be controlled by the application developer.

The BeanConnect crossware program model described in this document offers an alternative model that provides these features without requiring substantial rewriting of existing Java code. In fact, existing Java components (specifically visual IFC components subclassed from netscape.application.View, and visual AWT components subclassed from java.awt.component) can be used directly in a BeanConnect program without change.

A BeanConnect program offers the following advantages:

In the BeanConnect program model, a Java program is implemented in one or more HTML pages by embedding <OBJECT> tags in each page. The CLASSID attribute of an object tag indicates whether a Java object is a visual component used by the BeanConnect program (CLASSID="javabean"), or is a Java program object that is used to start and run the BeanConnect program when a user opens the HTML page (CLASSID="javaprogram"). There can only be one explicit Java object with the javaprogram CLASSID in each program, or there can be none.

A developer need not implement an explicit javaprogram object for a BeanConnect program. For example, a developer who uses JavaScript to interact with Java objects that themselves are used to enhance an HTML page may not be concerned with explicit control of the Java object lifetimes. In that case, a default object is automatically created to handle the program's lifetime and its objects. BeanConnect programs started and controlled from JavaScript contain only objects with the javabean CLASSID. The JavaScript code that initializes the application sets up an adapter that enables JavaScript to communicate with and use Java objects.

To permit direct communication between Java objects, to gain greater control over a program and its lifetime, and to develop multipage programs, a developer typically embeds as many objects as needed with the javabean CLASSID and embeds a single program object with the javaprogram CLASSID. The Java program object identifies a Java class that starts and controls the program when an HTML page is loaded. For more information about developing a Java program object, see Implementing a BeanConnect Program Using Java.

IMPLEMENTING A BEANCONNECT PROGRAM USING JAVASCRIPT

In its simplest incarnation, a BeanConnect program uses JavaScript to handle Java component command events. The visible aspects of this program consist of:

When a user opens the HTML page that contains a BeanConnect program of this type, a default Java program is started behind the scenes to control and manage the lifetimes of the Java objects used by the BeanConnect program.

KEY DEVELOPMENT ISSUES

The following points are of particular interest to all BeanConnect developers, particularly those who implement BeanConnect programs based on the simple JavaScript model:

The following sections highlight these development issues. In them, we develop a simple BeanConnect program that uses JavaScript to respond to a button press command event on an IFC button component by setting the value for a second IFC component, a read-only text field. The program also establishes a form that consists of two form elements, only one of which is visible. The visible element is a button that submits form data for processing. When a user clicks the submit button, the invisible form element reads the current value of the IFC text field component, and passes it as form data.

To view the full source code for this example, see Example 1: Using Existing Java Components in JavaScript.

SETTING UP A JAVASCRIPT TARGET ADAPTER

BeanConnect programs that rely on JavaScript to process command events received from Java components must use LiveConnect to establish a connection between Java components and JavaScript. There are three standard JavaScript steps for establishing the connection:

The creation of the LiveConnect adapter described here for the BeanConnect program is standard JavaScript practice for capturing an IFC component's command events. In this sample program, the JavaScript adapter object is implemented inside the <HEAD> tag on an HTML page as follows:

<head>
<title></title>
<script language=JavaScript>
function buttonWasPressed(arg1) {
   document.TheTextField.setStringValue("IFC button was pressed!");
}
var handler = new Object();
handler.onbuttonWasPressed = buttonWasPressed;
var e = new netscape.javascript.adapters.JSTargetAdapter(handler);
function setTheTarget() {
   document.TheButton.setCommand("buttonWasPressed");
   document.TheButton.setTarget(e);
}
</script>
</head>
The page header contains a definition for a JavaScript function that is used to process an event:

function buttonWasPressed(arg1) {
   document.TheTextField.setStringValue("IFC button was pressed!");
}
When called, this function sets the value in a text field to "IFC button was pressed!".

A new JavaScript object called "handler" is also constructed within the page header. The handler object is assigned a slot that links it to the previously declared buttonWasPressed() JavaScript function. Note that the event handler object must be constructed as a new object. It cannot be the same as the JavaScript document or layer objects.

var handler = new Object();
handler.onbuttonWasPressed = buttonWasPressed;
Next, the Target adapter object is constructed. The handler object is passed as an argument to the constructor. The adapter directs command events belonging to IFC components, such as button presses, to JavaScript event handlers for processing.

var e = new netscape.javascript.adapters.JSTargetAdapter(handler);
Finally, a second JavaScript function is defined:

function setTheTarget() {
   document.TheButton.setCommand("buttonWasPressed");
   document.TheButton.setTarget(e);
}
This function:

Note that an adapter is only needed for JavaScript so that it can receive command events from Java objects. The BeanConnect program model can also enable direct Java-to-Java communication, and does not require an adapter unless JavaScript is used to interact with the program or its objects.

For BeanConnect programs that use JavaScript, the Target object must be set after the adapter is implemented and the components that use it are initialized. In this sample BeanConnect program, the JavaScript function that declares and initializes the adapter is called when the HTML page is loaded:

<body onLoad="setTheTarget()">
EMBEDDING JAVA COMPONENTS

<OBJECT> tags are embedded on HTML pages to identify the Java components used by the BeanConnect program. The following example illustrates the key elements and parameters for the <OBJECT> tag:

<OBJECT CLASSID="javabean:netscape.application.Button"
   ID="TheButton" width=64 height=24>
<PARAM NAME="Title" VALUE="Push Me">
<PARAM NAME="Font" VALUE="Courier:Italic:12">
</OBJECT>
This embedded object tag indicates that the sample BeanConnect program uses an IFC component. The CLASSID element is a selector that indicates the Java object is a visual component that resides in a specific Java package (CLASSID="javabean"). The CLASSID element that represents Java components takes the form:

CLASSID="javabean:packagelocation.packagedobject"
Here, packagelocation indicates the package that contains the Java class, and packagedobject is the name of the class.

The ID element in the <OBJECT> tag provides a name for the object in the namespace for the HTML page (it performs a function similar to that of the NAME element in an <APPLET> tag). The ID element for each object in a program should be unique. Finally, the width and height elements apply only to components, and indicate the display size of the component on the page when the program runs.

Objects may have a variable number of embedded <PARAM> tags. Parameter tags identify the name and value for an object's properties, and actual parameters vary by component.

GATHERING JAVABEAN DATA TO USE AS FORM DATA

BeanConnect programs that use JavaScript can make use of a new element type, called object, for the <INPUT> tag. The object type creates a nonvisual form element that is used by the form to gather current data from a specified Java component elsewhere on the page. To be available to the object element on a form, a component, such as an IFC component, must implement the FormElement interface.

Forms that include the new object element type can query a specified Java component for its current data, and post that data with other form data when a user submits the form. The following example illustrates this new form for the <INPUT> tag:

<INPUT TYPE="object" NAME="TheTextField">
The Java component from which to gather data is specified by the NAME attribute. NAME should correspond to the ID attribute of a previously instantiated component declared as an object in the body of the HTML page. In this example, NAME points to a previously defined component, "TheTextField". Data is gathered from the component and is passed to the server as soon as a user presses the form's submit button.

UNDERSTANDING THE DEFAULT PROGRAM AND CONTROL OBJECTS

All BeanConnect programs use two Java objects to handle program logic, and to control the start-up and lifetime of the program and its Java components. These Java objects are referred to as the program object and the control object. The program object is a Java object that provides program-specific processing. The control object provides management services for the BeanConnect program and the Java components used by the program.

BeanConnect programs can either use a default program and control objects, or declare specific Java objects to use. Normally, simple BeanConnect programs that use JavaScript do not declare program or control objects. As a result, they are automatically provided with default Java program and control objects when a user loads the page containing the BeanConnect program. The program we are developing is an example of a BeanConnect program that uses the default program and control object.

All program objects, including the default program object, are derived from the Application class in netscape.application.

All control objects can implement the following interfaces:

The default control object implements both of these interfaces, so it can handle program start-up and lifetime, and the start-up, maintenance, and shutdown of the Java components used by the BeanConnect program.

The behavior of the default program and control objects are quite simple. When an HTML page containing a BeanConnect program is loaded, and the first embedded Java component (CLASSID="javabean") is encountered, the default Java program and control objects are started. The embedded Java component and all subsequently encountered Java components are automatically assigned to the default program object, and are maintained by the default control object. The default control object handles the lifetime of the program and the components it uses. The program is active as long as any page containing program objects is open. When all program pages are closed, meaning they are cleared from the history list, the program terminates.

Using the default program object makes most sense for simple BeanConnect programs, especially those that use LiveConnect to enable JavaScript interaction. Creating an explicit Java program object and implementing a control object gives a developer greater control over program lifetime, especially when a program spans pages or frames, as described in the following sections of this document.

IMPLEMENTING A BEANCONNECT PROGRAM USING JAVA

When developers need to create more complex BeanConnect programs that provide direct communication between Java objects, greater control over a program and its lifetime, and cross-page and cross-frame interactions, they can embed an object reference to an explicit Java program object in each HTML document belonging to the BeanConnect program. The embedded Java program object corresponds to a Java class that implements the program's logic. A required parameter tag for this object specifies the Java class that implements BeanConnect program and object lifetime management interfaces.

The parts of a BeanConnect program built using Java consist of: HTML documents used to provide the user interface to the program, the Java source code that implements the Java program object, and the Java source code that implements lifetime interfaces for the BeanConnect program and its objects. Each HTML page used by the BeanConnect program contains:

When a user opens the first HTML page that contains a BeanConnect program of this type, the Java program object is started behind the scenes, and its control object is also started to manage the lifetimes of the Java objects used by the program. When subsequent pages are opened, their Java program object references are linked to the instance of the program object that is already running.

KEY DEVELOPMENT ISSUES

The following points are of particular interest to BeanConnect developers creating a program controlled by an explicit Java program object:

The following sections highlight these development issues. In them, we develop a BeanConnect program that displays two data entry text fields in a frame on the left side of an HTML page, and a button and a read-only text field in a frame on the right side of the page. When a user enters a first and last name in the left frame, and then clicks the button in the right frame, the first name and last name from the left frame are concatenated and displayed in the text field in the right frame.

This sample program consists of three HTML documents and two Java source code files:

To view the full source code for this example, see Example 2: Direct Java-to-Java Communication, Spanning Frames.

EMBEDDING THE JAVA PROGRAM OBJECT

To embed an explicit Java program object in an HTML document, specify the object tag, and set its CLASSID to javaprogram. The Java program object must be the first object embedded in an HTML document.

In this sample application, the <OBJECT> tag for the Java program appears as follows:

<OBJECT CLASSID="javaprogram:MultiPageJavaApp" ID="TheProgram">
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
    <PARAM NAME="Embedded Owner" VALUE="MultiPageJavaAppOwner">
</OBJECT>
For Java program objects, CLASSID always takes the form:

CLASSID="javaprogram:packagelocation.packagedobject"
Here, packagelocation indicates the package that contains the Java class, and packagedobject is the name of the class.

The ID element in the <OBJECT> tag provides a name for the program object in the namespace for the HTML page (it performs a function similar to that of the NAME element in an <APPLET> tag).

An <OBJECT> tag for a Java program can contain the following <PARAM> tags:

Normally, it is good programming practice to include the "Program Name" parameter, if only to document the relationship between objects on a page. For multipage or multiframe programs, the "Program Name" parameter is a necessity.

In a multipage or multiframe BeanConnect program, the same Java program object declaration should appear in every document used by the BeanConnect program. This precaution guarantees that regardless of which program document a user first opens, the Java program object is always initialized correctly.

In this sample program, the object tag for MultiPageJavaApp appears in both Example_Multi_Java1.html and Example_Multi_Java2.html. These documents represent the frames used by the program.

EMBEDDING JAVA COMPONENTS

Embedding Java components in a BeanConnect program that uses Java to control program logic is very similar to embedding Java components for use in BeanConnect programs that use JavaScript. The main difference is that such embedded objects must now include a "Program Name" parameter tag with a value that corresponds to the value of the "Program Name" parameter for the previously declared Java program object. If the "Program Name" parameter differs or is missing, the component does not become part of the BeanConnect program and cannot be accessed from the program.

For example, here are the object declarations for the Java components that appear in the left frame of this sample BeanConnect program:

</OBJECT>
First name:
<OBJECT CLASSID="javabean:netscape.application.TextField"
        ID="FirstName" width=200 height=24>
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
</OBJECT>
<br>
Last name:
<OBJECT CLASSID="javabean:netscape.application.TextField"
        ID="LastName" width=200 height=24>
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
</OBJECT>
Here are the object declarations for the Java components that appear in the right frame:

<OBJECT CLASSID="javabean:netscape.application.Button"
        ID="DoSummary" width=100 height=24>
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
    <PARAM NAME="Title" VALUE="Concatenate">
</OBJECT>
<br>
Full name: <br>
<OBJECT CLASSID="javabean:netscape.application.TextField"
        ID="Summary" width=200 height=24>
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
    <PARAM NAME="Border" VALUE="null">
    <PARAM NAME="BackgroundColor" VALUE="lightgray">
    <PARAM NAME="Editable" VALUE="false">
</OBJECT>
Note that each of these objects specifies "Multi Page Java" for the value of its "Program Name" parameter, matching the value supplied by the Java program object.

For more information about Java component object declarations, see Embedding Java Components.

IMPLEMENTING THE JAVA PROGRAM OBJECT

The Java program object implements the main logic of a BeanConnect program. As such, the actual implementation of a Java program object differs for each BeanConnect program. Java program objects should be derived from the Application object in the netscape.application package. Programs that need to make use of utility classes, such as hash tables, may also want to import the netscape.util package. This sample BeanConnect program imports both of these packages for its Java program object.

MultiPageJavaApp.java is the source code for the main BeanConnect program. It implements a Connector class that links the frames in the application. The Connector method performCommand takes the input from two text field objects, concatenates them, and displays the results in a third, read-only text field. The MultiPageJavaApp class also implements methods that create, initialize, add, fetch, and remove objects that belong to the program. It also implements a method, wireObjects(), that links the program's button press event to the appropriate handler, which is, in turn, supplied by a connector object. MultiPageJavaApp's init() method instantiates the connector object used by wiredObjects().

For the complete source code for MultiPageJavaApp.java, see MultiPageJavaApp.java:

MultiPageJavaApp provides the BeanConnect program's unique functionality, but it does not start the program or control the program's lifetime. A program can access management services available through a Java control object, called an "Embedded Owner", specified as a parameter in the Java program object declaration in an HTML document used by the BeanConnect program. Recall that the <OBJECT> tag for MultiPageJavaApp included an embedded <PARAM> tag called "Embedded Owner", and that the value for that attribute is set to "MultiPageJavaAppOwner". MultiPageJavaAppOwner is the class that implements lifetime control for the program and its objects, and is described in the following section.

IMPLEMENTING THE JAVA CONTROL OBJECT

All BeanConnect programs use a Java program object to provide specific control over a program's logic, but they also use a second Java object, called an "embedded owner," to support the start-up and lifetime of the program and its Java components. This second object is a Java control object. The embedded owner of a BeanConnect program is identified in the "Embedded Owner" <PARAM> tag of the Java program object declaration. In the sample program, the declaration of the Java program is as follows:

<OBJECT CLASSID="javaprogram:MultiPageJavaApp" ID="TheProgram">
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
    <PARAM NAME="Embedded Owner" VALUE="MultiPageJavaAppOwner">
</OBJECT>
In the case of the sample BeanConnect program, the name of the Java control object is "MultiPageJavaAppOwner".

A developer typically implements one or two interfaces in the control object, depending on the needs of the BeanConnect program. The first interface, the EmbeddedBeanOwner interface, supports the initialization, starting, stopping, and destruction of individual Java components used by the BeanConnect program. The second interface, the EmbeddedProgramOwner interface, handles the initialization and shutdown of the BeanConnect program itself.

A control object's EmbeddedBeanOwner interface consists of the following methods:

The control object's EmbeddedProgramOwner interface consists of two methods:

Besides implementing these methods, developers can provide additional support methods for these interfaces. Such support methods are called from one or more of the embedded bean owner object's main methods to perform specific component or program lifetime processing.

UNDERSTANDING THE PROGRAM'S SEQUENCE OF EVENTS

How does the sample multiframe BeanConnect program work? When each frame document is loaded, the OBJECT tags in the document are processed in order. The first <OBJECT> tag that is encountered is the following, which is present in both frame documents:

<OBJECT CLASSID="javaprogram:MultiPageJavaApp" ID="TheProgram">
   <PARAM NAME="Program Name" VALUE="Multi Page Java">
   <PARAM NAME="Embedded Owner" VALUE="MultiPageJavaAppOwner">
</OBJECT>
This tag starts the program, an instance of the MultiPageJavaApp class. It also creates the embedded owner for the program, which is an instance of the MultiPageJavaAppOwner class.

When the "javabean:" <OBJECT> tags are processed, the system creates an instance of EmbeddedBeanTracker for each tag, and passes it to the embeddedBeanDidInit() method of the program's MultiPageJavaAppOwner instance. Here's the source code for the embeddedBeanDidInit() method:

public void embeddedBeanDidInit(EmbeddedBeanTracker beanTracker) {
   beanTracker.systemDefaultBeanOwner().embeddedBeanDidInit(beanTracker);
   Object object = beanTracker.getActualObject();
   String id = beanTracker.attribute("id");
   if ((object != null) && (id != null)) {
      MultiPageJavaApp app;
      app = (MultiPageJavaApp)beanTracker.application();
      app.addObject(id, object);
   }
}
The first thing this method does is to call the embeddedBeanDidInit() method of the system default EmbeddedBeanOwner. This, in turn, creates the actual object and embeds it into the HTML document. Next, this method retrieves the new actual object by calling the getActualObject() method of the beanTracker. It also retrieves the ID of the object using the beanTracker's attribute() method. After checking for validity of both these values, it retrieves the Application object for the program from the beanTracker, casting it up to its actual type, MultiPageJavaApp. Finally it calls the addObject() method of the Application object, and registering the component by name.

This sequence of events occurs for each "javabean:" <OBJECT> tag associated with this program. This means that all objects are registered with the application as they are created. When the BeanConnect program page containing Java components is closed, the reverse process takes place, and all components are unregistered by the embeddedBeanDidDestroy() method of the embedded owner:

public void embeddedBeanDidDestroy(EmbeddedBeanTracker beanTracker) {
   Object object = beanTracker.getActualObject();
   String id = beanTracker.attribute("id");
   if ((object != null) && (id != null)) {
      MultiPageJavaApp app;
      app = (MultiPageJavaApp)beanTracker.application();
      app.removeObject(id);
   }
}
But how does the program handle events for registered components? The answer lies in the wiredObjects() and addObject() methods of class MultiPageJavaApp.

void wireObjects() {
Object doSummary = getObject("DoSummary");
if (doSummary != null) {
((Button)doSummary).setTarget(connector);
((Button)doSummary).setCommand("changed");
}
}
public void addObject(String name, Object object) {
objects.put(name, object);
wireObjects();
}
Whenever an object is registered, the program calls wireObjects(). The wireObjects() method simply determines if an object called "DoSummary" is already registered. If so, the method sets the object up to send its Target command to the connector object. This object is of type Connector which is defined in the same file. The workhorse method in the Connector class is performCommand(), which implements the Target interface.

public void performCommand(String command, Object data) {
if ("changed".equals(command)) {
   Object firstName = application.getObject("FirstName");
   Object lastName = application.getObject("LastName");
   Object summary = application.getObject("Summary");
   if ((firstName != null) && (lastName != null)) {
      ((TextField)summary).setStringValue(
         ((TextField)firstName).stringValue() + " " +
         ((TextField)lastName).stringValue() );
   }
   else {
      ((TextField)summary).setStringValue(
         "Please open the forms page");
      }
   }
}
The performCommand() method attempts to retrieve registered objects called "FirstName", "LastName", and "Summary". It then makes sure firstName and lastName are found, which indicates that the document containing them is currently open. It extracts the text from these two objects, concatenates them, and places the result in the summary object. Note that the code does not check for the existence of the summary object. The reason is that the code knows that the summary object is in the same document as the button that started the command event, and therefore must be registered.

EXAMPLE BEANCONNECT PROGRAMS

The following sections provide the source code for the two sample BeanConnect programs described earlier in this document.

EXAMPLE 1: USING EXISTING JAVA COMPONENTS IN JAVASCRIPT

<html>
<head>
<title></title>
<script language=JavaScript>
function buttonWasPressed(arg1) {
   document.TheTextField.setStringValue("IFC button was pressed!");
}
var handler = new Object();
handler.onbuttonWasPressed = buttonWasPressed;
function setTheTarget() {
   var e = new netscape.javascript.adapters.JSTargetAdapter(handler);
   document.TheButton.setCommand("buttonWasPressed");
   document.TheButton.setTarget(e);
}
</script>
</head>
<body onLoad="setTheTarget()">
IFC Button:
<OBJECT CLASSID="javabean:netscape.application.Button"
   ID="TheButton" width=64 height=24>
<PARAM NAME="Type" VALUE="0">
<PARAM NAME="Title" VALUE="Push Me">
<PARAM NAME="Font" VALUE="Courier:Italic:12">
</OBJECT>
<br>
IFC TextField:
<OBJECT CLASSID="javabean:netscape.application.TextField"
   ID="TheTextField" width=256 height=24>
<PARAM NAME="Editable" VALUE="false">
<PARAM NAME="BackgroundColor" VALUE="lightGray">
<PARAM NAME="Font" VALUE="Dialog:Plain:12">
</OBJECT>
<br>
<FORM ACTION="Example_Empty.html" METHOD=GET>
HTML button:
<INPUT TYPE="object" NAME="TheTextField">
<INPUT TYPE="submit" NAME="SubmitButton" VALUE="Submit">
</FORM>
</body>
</html>
So how does this BeanConnect program work? A user sees a web page that consists of an IFC button labeled "Push Me," an empty, read-only, IFC text field control, and an HTML button labeled "Submit".

When the user clicks the "Push Me" button, an IFC command event is generated. The event is captured by the JSTargetAdapter object and passed to the JavaScript "buttonWasPressed" function. The function sets the value of the IFC text field control to "IFC button was pressed!". If the user then clicks the Submit button, the form reads the current value of the IFC text field control and passes it to the form's action handler. In this example, the current text string of the text field control is read into a new HTML page called "Example_Empty.html". The contents of the page can be examined to determine if the application behaved as expected.

EXAMPLE 2: DIRECT JAVA-TO-JAVA COMMUNICATION, SPANNING FRAMES

This BeanConnect example consists of five parts: three HTML documents and two Java source-code files. The HTML documents contains object tags that describe the program's Java objects and their parameters. The Java source-code file defines the Java class that starts and controls the program.

The first HTML document: Example_Multi_Java.html
Example_Multi_Java.html sets up an HTML page with two frames of equal size. The contents of each frame are read from separate HTML source files. These source files define the text and controls visible in each frame.

<html>
<title>Java Program to test multiple documents connected with Java</title>
<frameset cols="50%,50%">
<FRAME NAME=JavaFrame1 SRC="Example_Multi_Java_1.html">
<FRAME NAME=JavaFrame2 SRC="Example_Multi_Java_2.html">
</frameset>
<html>
The second HTML document: Example_Multi_Java_1.html
Example_Multi_Java_1.html defines the contents of the left frame defined by the previous HTML document, Example_Multi_Java.html:

<html>
<head>
</head>
<body>
<OBJECT CLASSID="javaprogram:MultiPageJavaApp" ID="TheProgram">
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
    <PARAM NAME="Embedded Owner" VALUE="MultiPageJavaAppOwner">
</OBJECT>
First name:
<OBJECT CLASSID="javabean:netscape.application.TextField"
        ID="FirstName" width=200 height=24>
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
</OBJECT>
<br>
Last name:
<OBJECT CLASSID="javabean:netscape.application.TextField"
        ID="LastName" width=200 height=24>
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
</OBJECT>
</body>
</html>
The third HTML document: Example_Multi_Java_2.html
Example_Multi_Java_2.html defines the contents of the right frame defined for the master HTML document, Example_Multi_Java.html:

<html>
<head>
</head>
<body>
<OBJECT CLASSID="javaprogram:MultiPageJavaApp"
        ID="TheProgram">
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
    <PARAM NAME="Embedded Owner" VALUE="MultiPageJavaAppOwner">
</OBJECT>
Click here to concatenate first and last names entered the other frame:
<OBJECT CLASSID="javabean:netscape.application.Button"
        ID="DoSummary" width=100 height=24>
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
    <PARAM NAME="Title" VALUE="Concatenate">
</OBJECT>
<br>
Full name: <br>
<OBJECT CLASSID="javabean:netscape.application.TextField"
        ID="Summary" width=200 height=24>
    <PARAM NAME="Program Name" VALUE="Multi Page Java">
    <PARAM NAME="Border" VALUE="null">
    <PARAM NAME="BackgroundColor" VALUE="lightgray">
    <PARAM NAME="Editable" VALUE="false">
</OBJECT>
</body>
</html>
MultiPageJavaApp.java:
MultiPageJavaApp.java is the source code for the Java program object that essentially functions as the main BeanConnect program.

import netscape.application.*;
import netscape.util.*;
class Connector implements Target {
    MultiPageJavaApp application;
    Connector(MultiPageJavaApp application) {
        this.application = application;
    }
    public void performCommand(String command, Object data) {
        if ("changed".equals(command)) {
            Object firstName = application.getObject("FirstName");
            Object lastName = application.getObject("LastName");
            Object summary = application.getObject("Summary");
            if ((firstName != null) && (lastName != null)) {
                ((TextField)summary).setStringValue(
                        ((TextField)firstName).stringValue() + " " +
                        ((TextField)lastName).stringValue() );
            } else {
                ((TextField)summary).setStringValue(
                        "Please open the forms page");
            }
        }
    }
}
public class MultiPageJavaApp extends Application {
    Hashtable objects;
    Connector connector;
    void wireObjects() {
        Object doSummary = getObject("DoSummary");
        if (doSummary != null) {
            ((Button)doSummary).setTarget(connector);
            ((Button)doSummary).setCommand("changed");
        }
    }
    public void init() {
        super.init();
        objects = new Hashtable();
        connector = new Connector(this);
    }
    public void addObject(String name, Object object) {
        objects.put(name, object);
        wireObjects();
    }
    public void removeObject(String name) {
        objects.remove(name);
    }
    public Object getObject(String name) {
        return objects.get(name);
    }
}
MultiPageJavaAppOwner.java:
Program start-up and lifetime is managed for all BeanConnect programs by an EmbeddedBeanOwner or an object implemented from it. MultiPageJavaApp, the example BeanConnect program described here, derives a new class, MultiPageJavaAppOwner, from the default EmbeddedBeanOwner object.

import netscape.util.*;
import netscape.application.*;
import netscape.applet.*;
public class MultiPageJavaAppOwner implements EmbeddedBeanOwner, EmbeddedProgramOwner {
    public void embeddedBeanDidInit(EmbeddedBeanTracker beanTracker) {
        beanTracker.systemDefaultBeanOwner().embeddedBeanDidInit(beanTracker);
        Object object = beanTracker.getActualObject();
        String id = beanTracker.attribute("id");
        if ((object != null) && (id != null)) {
            MultiPageJavaApp app;
            app = (MultiPageJavaApp)beanTracker.application();
            app.addObject(id, object);
        }
    }
    public void embeddedBeanDidStart(EmbeddedBeanTracker beanTracker) {
    }
    
    public void embeddedBeanDidStop(EmbeddedBeanTracker beanTracker) {
    }
    
    public void embeddedBeanDidDestroy(EmbeddedBeanTracker beanTracker) {
        Object object = beanTracker.getActualObject();
        String id = beanTracker.attribute("id");
        if ((object != null) && (id != null)) {
            MultiPageJavaApp app;
            app = (MultiPageJavaApp)beanTracker.application();
            app.removeObject(id);
        }
    }
    public void programDidInit(EmbeddedProgramTracker programTracker) {
    }
    public boolean programCanShutdown(EmbeddedProgramTracker programTracker) {
        return true;
    }
}

BEANCONNECT CLASS AND INTERFACE REFERENCE

This section describes the classes and interfaces for BeanConnect programs.

interface netscape.applet.EmbeddedProgramOwner

This interface provides control over the behavior of the program object. A developer must implement the interface as part of a Java class, and specify the name of this class as the "embedded owner" parameter in a "javaprogram:" <OBJECT> tag.

public interface EmbeddedProgramOwner { 
public void programDidInit(EmbeddedProgramTracker programTracker); 
public boolean programCanShutdown(EmbeddedProgramTracker programTracker); 
     }
For more information about creating an embedded owner object that overrides the default embedded owner, see Overriding default embedded owners.

public void programDidInit(EmbeddedProgramTracker programTracker);
Called after the Application object for the program is constructed, and its init() method has been called.

public boolean programCanShutdown(EmbeddedProgramTracker programTracker);
Called when the system wants to shut down the program. This happens when all HTML documents associated with the program have been closed. Closing means that a document has been trimmed from the history list. If the program returns false, then the system does not shut down the program itself. In this case the developer must provide another way for the program to shut down, or can let the program shut down when the Java virtual machine shuts down.

interface netscape.applet.EmbeddedBeanOwner

Individual Java components in a program can be created and maintained by providing an implementation of this interface. The class implementing this interface can be specified as the "embedded owner" parameter in either the "javaprogram:" or "javabean:" <OBJECT> tags.

public interface EmbeddedBeanOwner { 
public void embeddedBeanDidInit(EmbeddedBeanTracker beanTracker); 
public void embeddedBeanDidStart(EmbeddedBeanTracker beanTracker); 
public void embeddedBeanDidStop(EmbeddedBeanTracker beanTracker); 
public void embeddedBeanDidDestroy(EmbeddedBeanTracker beanTracker); 
} 
For more information about creating an embedded bean owner object that overrides the system default embedded bean owner, see Overriding default embedded owners.

public void embeddedBeanDidInit(EmbeddedBeanTracker beanTracker);
Called after the system has finished preparing for embedding a Java component. This method is responsible for actually creating and embedding the object itself.

public void embeddedBeanDidStart(EmbeddedBeanTracker beanTracker);
Called when the HTML document containing a Java component is made current. For example, this method is called if the user loads another document and then clicks the back button to return to document containing the component.

public void embeddedBeanDidStop(EmbeddedBeanTracker beanTracker);
Called when the HTML document containing a Java component is added in the history list. For example, this happens when another HTML document is loaded into the same window.

public void embeddedBeanDidDestroy(EmbeddedBeanTracker beanTracker);
Called when the resources for embedding a Java component are destroyed. For example, this happens when the HTML document containing the component is removed from a window's history list, and when the browser is shut down.

class netscape.applet.EmbeddedProgramTracker

This class provides embedded program services and information that can be used by the developer of a BeanConnect program. An instance of EmbeddedProgramTracker is passed as a parameter to all methods in the EmbeddedProgramOwner interface. This instance is created and maintained by the system, and represents the "javaprogram:" <OBJECT> tag used to start the program.

public class EmbeddedProgramTracker { 
public String className(); 
public URL documentURL(); 
public URL codebaseURL(); 
public String attribute(String name); 
public String parameter(String name); 
public Enumeration parameterKeys(); 
public Enumeration parameterValues(); 
public Application application(); 
} 
public String className();
Returns the value of the ID attribute for the <OBJECT> tag used to start a program. The ID attribute specifies a name for reflection of the object into JavaScript, but it can be used by the program to register and locate the object in Java as well.

public URL documentURL();
Returns a URL object that corresponds to the document that contains the "javaprogram:" <OBJECT> tag used to start a program.

public URL codebaseURL();
Returns a URL object that represents the codebase from which the program objects are loaded. By default, the codebase is the same as the location of the document that contains the <OBJECT> tags for the given program. The CODEBASE attribute of the <OBJECT> tag can, however, specify a different codebase.

For more detailed information about using the CODEBASE attribute, see Using the CODEBASE attribute.

public String attribute(String name);
Returns the value for the <OBJECT> tag attribute specified by name, or null if no such attribute is found.

public String parameter(String name);
Returns the value for the <OBJECT> tag parameter specified by name, or null if no such parameter is found.

public Enumeration parameterKeys();
Returns an Enumeration object for the list of parameter keys (names) in an <OBJECT> tag. The order of this enumeration is the same as that of the one returned by the parameterValues() method.

public Enumeration parameterValues();
Returns an Enumeration object for the list of parameter values in an <OBJECT> tag. The order of this enumeration is the same as that of the one returned by the parameterNames() method.

public Application application();
Returns the Application object for a BeanConnect program. This is the instance of the class specified by the CLASSID attribute of the <OBJECT> tag.

class netscape.applet.EmbeddedBeanTracker

EmbeddedBeanTracker provides embedded Java component services and information that can be used by the developer of a BeanConnect program. An instance of EmbeddedBeanTracker is passed to all methods of the EmbeddedBeanOwner interface. This instance is created and maintained by the system, and represents the "javabean:" <OBJECT> tag that orignally embedded a specific component into an HTML document.

public class EmbeddedBeanTracker { 
public String className(); 
public URL documentURL(); 
public URL codebaseURL(); 
public String attribute(String name); 
public String parameter(String name); 
public Enumeration parameterKeys(); 
public Enumeration parameterValues(); 
public Application application(); 
public Rect bounds(); 
public Frame frame(); 
public RootView rootView(); 
public void setActualObject(Object actualObject); 
public Object getActualObject(); 
public EmbeddedBeanOwner systemDefaultBeanOwner(); 
public EmbeddedBeanOwner programDefaultBeanOwner(); 
} 
public String className();
Returns the value of the ID attribute for the embedded <OBJECT> tag. The ID attribute specifies a name for reflection of the object into JavaScript, but it can be used by the program to register and locate the object in Java as well.

public URL documentURL();
Returns a URL object that corresponds to the document that contains the "javaprogram:" <OBJECT> tag used to start a program.

public URL codebaseURL();
Returns a URL object that represents the codebase from which program objects are loaded. By default, the codebase is the same as the location of the document that contains the <OBJECT> tags for a given program. However, the CODEBASE attribute of the <OBJECT> tag can specify a different codebase.

For more detailed information about using the CODEBASE attribute, see Using the CODEBASE attribute.

public String attribute(String name);
Returns the value for the <OBJECT> tag attribute specified by name, or null if no such attribute is found.

public String parameter(String name);
Returns the value for the <OBJECT> tag parameter specified by name, or null if no such parameter is found.

public Enumeration parameterKeys();
Returns an Enumeration object for the list of parameter keys (names) in an <OBJECT> tag. The order of this enumeration is the same as that of the one returned by the parameterValues() method.

public Enumeration parameterValues();
Returns an Enumeration object for the list of parameter values in an <OBJECT> tag. The order of this enumeration is the same as that of the one returned by the parameterNames() method.

public Application application();
Returns the Application object for the program associated with an <OBJECT> tag. The program is either a default program created by the system, or an explicit program specified by the CLASSID attribute of a "javaprogram:" <OBJECT> tag.

public Rect bounds();
Returns a Rect object containing the coordinate values for placement of an actual object in its container.

public Frame frame();
Provides an AWT Frame object as the container for the actual object. It is used when embedding AWT objects.

For more information about embedding actual objects, see Rules for Embedding Actual Objects.

public RootView rootView();
Provides an IFC RootView as the container for the actual object. It is used when embedding IFC objects.

For more information about embedding actual objects, see Rules for Embedding Actual Objects.

public void setActualObject(Object actualObject);
Informs the system about the actual object to embed.

For more information about embedding actual objects, see Rules for Embedding Actual Objects.

public Object getActualObject();
Returns the actual embedded object.

public EmbeddedBeanOwner systemDefaultBeanOwner()
Returns the system default EmbeddedBeanOwner object. The default EmbeddedBeanOwner object knows how to embed AWT and IFC objects, and how to initialize such objects given the <OBJECT> tag's parameters.

public EmbeddedBeanOwner programDefaultBeanOwner();
Returns the default EmbeddedBeanOwner for the program. A "javaprogram:" <OBJECT> tag can specify an embedded owner to override the default system EmbeddedBeanOwner, and each "javabean:" <OBJECT> tag can further override this setting for itself.

For more information, see Overriding default embedded owners.

class netscape.application.FormElement

Implement this interface to enable an object to participate in HTML form submission. A new INPUT tag type, "object", enables references to <OBJECT> tags as form elements. The syntax of this INPUT tag is:

<INPUT TYPE="OBJECT" NAME="ObjectName"> 
The NAME attribute refers to the ID name of an <OBJECT> tag that must appear before this INPUT tag in the HTML document. The FormElement interface contains a single method. This method should return the text value to submit for this object as part of form submission.

public interface netscape.application.FormElement { 
   public String formElementText(); 
}
public String formElementText();
Returns a string value to be used by the form submission system.

USING THE CODEBASE ATTRIBUTE

The CODEBASE attribute provides a way to specify a codebase for a Java object when that codebase differs from the location from which the HTML container page is loaded. CODEBASE is only meaningful for BeanConnect programs that use the default Java program object. When the default program is used, its codebase can be explicitly specified by the first "javabean:" <OBJECT> tag. All subsequent CODEBASE attributes are ignored.

The use of CODEBASE attribute in a "javabean:" <OBJECT> tag has no effect if the program associated with the <OBJECT> tag was specified explicitly using a "javaprogram:" <OBJECT> tag. The codebase in use in that case is the one specified by the "javaprogram:" <OBJECT> tag

When "javaprogram:" <OBJECT> tags for a single program are used on multiple pages, the CODEBASE attribute of the first loaded object is used, and all the other ones are ignored.

These rules are meant to ensure that all program objects are loaded from a single codebase for reasons of security.

RULES FOR EMBEDDING ACTUAL OBJECTS

It is the responsibility of the EmbeddedBeanOwner to create an actual object and place it in the container provided by EmbeddedBeanTracker. AWT objects should be placed in the Frame object provided by the frame() method. IFC objects should be embedded in the RootView object provided by the rootView() method.

The class name of the actual object can be retrieved using the className() method. The EmbeddedBeanOwner is also responsible for calling the setActualObject() method to inform the system about the actual object that it creates. To simulate default embedding behavior, use the systemDefaultBeanOwner() method in the body of EmbeddedBeanOwner.embeddedBeanDidInit():

beanTracker.systemDefaultBeanOwner().embeddedBeanDidInit(beanTracker); 
After this call, the actual object created by the default bean owner can be obtained by calling the getActualObject() method.

OVERRIDING DEFAULT EMBEDDED OWNERS

The system provides default implementations of EmbeddedBeanOwner and EmbeddedProgramOwner interfaces. These objects are used by default programs, and by programs that specify no embedded owners of their own. When a "javaprogram:" <OBJECT> tag specifies an embedded owner, the system instantiates the specified object, and then verifies that it implement one or both of these interfaces. If so, this instance is used to override either or both the default values for the given program. For example, if a class MyEmbeddedOwner is specified, and it implements both EmbeddedBeanOwner and EmbeddedProgramOwner, then this object is used as the embedded owner for the program and all of the Java components associated with it.

Developers can further customize this behavior for an individual component by specifying an object for it that implements the EmbeddedBeanOwner interface. This object is used to override the system and program defaults for the given component.

The default EmbeddedBeanOwner provides some useful features that a developer may wish to use. In some cases, furthermore, the developer may want to override only some of the features of the program's own default bean owner for an individual component. For this reason, the EmbeddedBeanTracker object provides two methods to gain access to the system and program default bean owners:

public EmbeddedBeanOwner systemDefaultBeanOwner(); 
public EmbeddedBeanOwner programDefaultBeanOwner(); 
If the "javaprogram:" <OBJECT> tag does not specify an EmbeddedBeanOwner, then both these routines return the system default bean owner.

USING PARAM ATTRIBUTES

As part of "javabean:" <OBJECT> tags, a developer may embed <PARAM> tags to specify parameters for the object. The default system EmbeddedBeanOwner interprets such parameters as possible initialization values for the actual object. The rules for this activity are given here. For example, given the following object tag:

<OBJECT CLASSID="javabean:netscape.application.Button" ID="ActionButton" 
WIDTH=64 HEIGHT=24> 
<PARAM NAME="Title" VALUE="Action"> 
<PARAM NAME="Color" VALUE="green"> 
</OBJECT> 
The actual object is first instantiated based on the class name provided by the CLASSID attribute. In this case the actual object is of type netscape.application.Button. The system checks to ensure that this object is a subclass of either netscape.application.View or java.awt.Component.

Once the object exists, the system inspects the object and attempts to map the NAME attributes of the <PARAM> tags onto setter routines. For example, given the "Title" and "Color" parameter names, the system looks for methods on the objects called setTitle() and setColor(). If such methods are located, and if they take a single argument and return nothing (void,) then the qualified methods are used to initialize the object.

The argument for each initialization call is constructed as follows. The value of the VALUE attributes is used in an attempt to create an appropriate argument object for the given methods. For example, the value "Action" yields a String object with the value "Action", and the value "green" yields a Color object with RGB value of 0x00FF00.

In some cases an object may require initialization based on methods that need to be called on some embedded objects. For example, objects of type netscape.application.ListView allow the default text color for items to be specified like this:

     listView.prototypeItem().setTextColor(Color.green); 
To allow such initialization, the system actually parses the NAME attributes a bit more closely. If these names contain embedded period (.), then the system attempt to locate the embedded objects in a given object that qualifies for the given name. The rule here is that the embedded object must be available through a field or simple method with the given name. For example, the <PARAM> tag

     <PARAM NAME="prototypeItem.TextColor" VALUE="green"> 
works for a netscape.application.ListView, because this class has a method named prototypeItem() that takes no arguments and returns an object of type netscape.application.ListItem. This object, in turn, has a method called setTextColor(), which takes a single argument of type Color, and returns void. The author can specify embedded objects to depths greater than one as well.

Finally, there are two special parameters recognized by the system default EmbeddedBeanOwner for use with IFC components. These are:

NAME="View Has Vertical Scroll Bar" 
NAME="View Has Horizontal Scroll Bar" 
A value of "true" for either of these parameters embeds the actual object in an intermediate ScrollGroup object. This is how IFC components such as ListView and TextView get to have scroll bars.

For the latest technical information on Sun-Netscape Alliance products, go to: http://developer.iplanet.com

For more Internet development resources, try Netscape TechSearch.


Copyright © 1999 Netscape Communications Corporation.
This site powered by: Netscape Enterprise Server and Netscape Compass Server.