Check out the new USENIX Web site.
Using JavaUSENIX

  rao_prithvi

by Prithvi Rao
<prithvi@kiwilabs.com>

Prithvi Rao is the founder of Kiwilabs, which specializes in software engineering methodology and Java training. He has worked on the development of the MACH OS and a real-time version of MACH, and he holds two patents resulting from his work on mobile robots.

Using Beans within ActiveX

We live in a world of diversity, and the computing industry is no exception. Recently, I was writing some ActiveX code just to learn more about it, and I had an epiphany: Java Beans and ActiveX are remarkably similar.

My first thought was, "Why should I bother learning this technology?" My second was, "maybe I shouldn't." I am not suggesting that ActiveX is either a lesser or a redundant technology, but that it is an alternative to Java Beans. It also does not mean that if you write code in Java and it acts like a Bean, you are excluded from ever incorporating your Beans as reusable components into an ActiveX environment.

The focus of this article is precisely how to do just that. I am going to go through the steps of taking a piece of code written as a Java Bean and embed the Bean into an ActiveX control. I am going to look at the ActiveX bridge provided with the Beans Development Kit from Sun (BDK 1.0, <https://java.sun.com>).

The reasons for doing this are quite compelling. ActiveX and Beans are the two main component architectures. ActiveX, which is based on the Component Object Model (COM) from Microsoft, first made its debut in 1992. Recently, Sun came out with its component architecture, Java Beans, and it has gained a great deal of popularity since its inception in 1997. Java Beans are written entirely in Java and require a JVM. The Java Development Kit is available from <https://www.javasoft.com>.

I am not going to deal with the ActiveX side of things except where it is necessary to understand the process.

Beans and ActiveX

The following summarizes the two component architectures:

BeansActiveX
Written in JavaWritten in C, C++, or VB
Requires a JVMRequires COM
!PointersPointers
Simple to useComplex to use
My experiences and those of my colleagues lead me to the opinion that it is relatively difficult to learn ActiveX in a short time and be productive. However, if you have a large investment in ActiveX code and all your new and recent hires (who all happen to Java devotees) are going to be developing components using Beans that will work with legacy ActiveX code, then read on.

Beans Defined

A Java program is a Bean under the following conditions:

  1. Its private data fields are available using accessor methods.
  2. Accessor methods are public methods.
  3. Standard design patterns are used to name private data fields.
  4. It uses introspection or a BeanInfo class to get information about private data fields.
  5. It can be used with property editors.
  6. It can be serialized to provide persistence.
  7. It uses a delegation model for handling events.
Beans expose properties, events, and methods; this is identical to ActiveX. Regardless of how an ActiveX control was written, it won't know that it is interacting with a Bean if we can find a way to expose the properties, events, and methods of the Bean to the ActiveX control. This is where the ActiveX bridge comes in.

The ActiveX container and the Bean never communicate directly; everything goes through the bridge. Currently, the bridge is in its third beta release.

Let's create a visible Bean (the second beta release supported only visible Beans) to see how to "bridge" the gap.

Writing the Bean

The following Bean is from Rob Englander's book, Developing Java Beans, and I use it with his permission. We are going to look at code for the BeansBook.Simulator. VisualTemperature class. Let's call this file Simulator.java and put it in ~/projects/MyBeans/Java.

package BeansBook.Simulator

import java.beans.*;
import java.awt.*;

// let's define the temperature bean class
public class VisualTemperature extends Panel
 implements TemperaturePulseListener //detector listener
  java.io.Serializable // make it serializable
{

// provide support for bound property listeners
protected PropertyChangeSupport boundSupport;

// the current temperature
protected double theTemperature = 22.0;

// constructor for this class
public VisualTemperature()
{
 // construct the support object
 boundSupport = new PropertyChangeSupport(this);
}
 // add a property change listener
 public void addPropertyChangeListener(PropertyChangeListener)
 {
  // defer to the support object
  boundSupport.addPropertyChangeListener(1);
}

// remove a property change listener
public void removePropertyChangeListener(PropertyChangeListener 1)
{

 // defer to support object
 boundSupport.removePropertyChangeListener(1);
}

 // get the value of the Temperature property
public double getTemperature()
{
 return theTemperature;
}

 // set the value of the Temperature property
public void setTemperature(double t)
{
 // do nothing if the value did not change
  if (t == theTemperature)
  {
    return;
  }
 // save the old value
  Double old = new Double(thetemperature);

  // save the new value
  theTemperature = t;

  // fire the property change event
  boundSupport.firePropertyChange("Temperature", old new
            ;Double(t)); }

 // handle a temperature pulse
 public void temperaturePulse(TemperaturePulseEvent evt)
{
  // get the pulse temperature
  double p = evt.getPulseTemperature();

  // get the current temp
  double c = getTemperature();

  // if the pulse temp is > current temp
  if (p > c)
  {
   // only change if the difference is > 1
   if ((p - c) >= 1.0)
   {
    // add 1 to the current temperature
    setTemperature(c + 1.0);
   }
  }
 }
 // take a temperature pulse by a direct method call
 public void directTemperaturePulse(double pulse)
 {
  // emulate a regular temperature pulse
  temperaturePulse(new TemperaturePulseEvent (null, pulse));
 }
}

This Bean conforms to standard design patterns for accessor methods, handling events, and so forth. I'll discuss design patterns in more detail in subsequent articles.

Jarring the Bean

All Beans are "packaged" as Java ARchive files (JAR). If we want to embed the Bean in an ActiveX control, we need to create this archive file. I'll call it Simulator.jar. The first thing to do is to compile the Simulator.java file:

javac Simulator.java

This creates a class file called Simulator.class

Next, create a JAR file by using the jar utility that is part of the JDK. Go to the directory containing the Simulator.class file, and run the jar utility:

jar vcf Simulator.class Simulator.jar

This command is a directive to create a new archive called Simulator.jar and make the file Simulator.class be part of it. The v switch provides verbose output and is not absolutely necessary. You might have observed that jar is very similar to the tar utility. Jar essentially compresses the file. This is especially important because Beans are intended to be accessed across a network.

Packaging the Bean

This is the main step that actually makes the Java Bean recognizable by the ActiveX control.

First, create a directory where you can place all the output from the Packager. This is where all the type libraries and registry files created will be placed, as well as the Java stub files. All of these are outputs of the Packager.

mkdir ~/projects/MyBeans/ActiveX

Now copy the beans.ocx file in bdk/bridge/classes into this directory. This is the copy of the beans.ocx that will be referenced by the ActiveX versions of the simulator Beans.

Before we run the Packager, we need to set the CLASSPATH environment:

setenv CLASSPATH ~/bdk/bridge/classes

Now we can run the Packager:

java sun.beans.ole.Packager

The Packager presents you with a dialog box that walks you through the steps needed to package a Bean. Here are the steps:

 1. Specify the JAR file previously created containing the Bean. You can type in the full pathname of the file

~/projects/MyBeans/Java/Simulator.jar

 2. The dialog box changes to show the Beans contained in the JAR file. Select the class "BeansBook.Simulator.Thermostat," and press the "Next" button.

 3. Now you have to specify the ActiveX name that should be used to identify the component. Let's use "JavaThermostat," and press the "Next" button.

 4. Now specify the directory into which the type library and the registry files are to be placed. These must be in the same directory as the beans.ocx file. (Remember we copied it into ~/projects/MyBeans/ActiveX.)

 5. Next we are asked if we wish to "crack" the events. The discussion on this topic is for another time. For now let's "crack" the parameters. This means that event is fired into the ActiveX event firing protocol.

 6. Now start the packaging process by pressing the "Start Generation" button.

The Packager tool adds new classes to the JAR file, and these classes all start with ole, which stands for "Object Linking and Embedding." One new class supports the Bean's ActiveX control interface. The rest are to support the ActiveX control event listeners.

If you wanted to use the Bean in a Microsoft Word document, you would use the Object command to select this control. The Java Bean can now be used anywhere an ActiveX component can be placed.

Conclusion

Understanding interoperability is a fundamental requirement of the computing world because it is one way to bridge the gap between newer and older technologies. Examples of this are CORBA/DCOM and JDBC/ODBC. The popularity of Java, and therefore Beans, is increasing, but the ability for Beans to interoperate with other component architectures will partially determine its success. Java Beans encourages the programmer to live in the design space of a problem. With the powerful, easy-to-use tools provided by the BDK distribution, we can make interoperability a reality.

 

?Need help? Use our Contacts page.
First posted: 8th July 1998 efc
Last changed: 8th July 1998 efc
Issue index
;login: index
USENIX home