Using JavaBeans with Microsoft ActiveX ComponentsJavaBeans components may be used as embedded objects or Microsoft ActiveX components within applications such as Microsoft Office, Internet Explorer, and Visual Basic. This document provides an overview of the Java Plug-in that acts as a bridge and instructions on how to package and register JavaBeans as ActiveX components. This mechanism permits applets to be accessed from Javascript within Internet Explorer. Unfortunately the current Netscape Plug-in APIs do not permit scripting of Plug-ins within Netscape Navigator. However Sun and Netscape are working together to implement a new interface ("OJI") that will permit full scripting of Java Plug-in in future releases of Netscape Navigator. OverviewTo use a JavaBean as an embedded object, you package the JavaBean and then use it as an ActiveX component. A registry file (text file) and a type library are created by the packager. This registry contains an object id, the executable path for the component, bridge information, and a type library path. The TypeLib file is a binary file that describes each component's properties, events, and methods.
Packaging and RegistrationStep 0: Start the PackagerTo open the packager, run the following command from your Java Plug-in installation directory (in most cases this will be c:\program files\javasoft\jre\1.3\): bin\java.exe -cp lib\jaws.jar sun.beans.ole.Packager The packager will guide you through five steps to package your JavaBean. Step 1: Specify the JAR FileSpecify the JAR file that contains the JavaBean to be packaged and press Next.
Step 2: Select the JavaBeans ComponentThe packaging tool lists all the JavaBeans inside the JAR file you specified in step 1. Select the JavaBean to be packaged and press Next.
Step 3: Specify an ActiveX NameThe packaging tool suggests an ActiveX name for the JavaBean. This name will be used in the ActiveX environment to refer to the component. The packager gives you a default name (the name of the JavaBean minus its java package name prefix).
Step 4: Specify an Output DirectoryThe packager creates a registry file (.reg) and a type library (.tlb) in a directory that you specify. Note that the registry file contains information on the location of the type library file. If you move the type library file, you will need to manually update the registry file and register it again. The location of the beans.ocx (Java Plug-in ActiveX component) is determined from the registry settings of the Java Plug-in installation. Again, if you move the beans.ocx, you will need to manually modify this file. .
Step 5: Start GenerationThe packager can automatically register the component for you on the local machine. If you choose to register the registry file, the JavaBeans component will be automatically useable in an ActiveX container.
Command Line OptionsThe packager can be invoked from the command line with the following arguments: java sun.beans.ole.Packager
You may specify options in any order. You must use the -jar option; the packager will use the following default values for options that you do not specify.
The packager displays status messages in the standard output of the command prompt (usually the window in which you started the packager). Using JavaBeans as ActiveX ComponentsThe following example uses the Microsoft Visual Basic development environment to illustrate how two sample JavaBeans, ExplicitButton and Juggler, may be used as ActiveX components. Importing JavaBeans into Visual BasicFrom within Visual Basic, select the "Tools" menu and "Custom Controls" item and add the ExplicitButtonBeanControl and JugglerBeanControl as shown below.
After importing the custom controls, Juggler and ExplicitButton will appear on the toolbar. Example: You can work with Juggler and ExplicitButton in the same way as you would with ordinary ActiveX components. For example, instantiate a Juggler and two ExplicitButtons in the Visual Basic form. Label the ExplicitButtons "Start" and "Stop" in the Properties window (by editing the "Label" property). Alternatively, you can invoke the customizer on the JavaBean (if the JavaBean has a customizer) by right-clicking on the component and selecting the Properties menu as shown below:
Once the customizer is open, modify the label of the button. Notice that the label changes in the Visual Basic properties tool bar. This occurs because the button fires a PropertyChangeEvent which is caught by the bridge and forwarded to the container (in this case Visual Basic). The customizer is also available through the normal PropertyPages mechanism of the ActiveX specifications. Please refer to your ActiveX container documentation on how to open the property pages of an ActiveX component.
Double-click on the "Start" button and add the event-handling Visual Basic code, Juggler1.start, to the ExplicitButton1_actionPerformed subroutine as illustrated below.
Juggler1 is the value for the "name" property for the Juggler JavaBean component running on the same page. Now, double-click on the "Stop" button and add the event handling Visual Basic code, Juggler1.stop, to the ExplicitButton2_actionPerformed subroutine. Run the program and test your work by pressing the "Start" and "Stop" buttons to start and stop the juggler. Add an ActiveX scrollbar component and use it to control the juggler's animation speed. Set the scroll-bar maximum value property to 0 and the minimum value to 200. Now, double-click on the scrollbar to edit the HScroll1_Change subroutine as shown below.
Run the program. You can now increase and decrease Juggler's animation speed by moving the scrollbar right and left.
Minimum Requirements for Distributing Packaged JavaBeansWhen packaged JavaBeans are distributed across machines (including the Internet), the following requirement must be met for the packaged JavaBeans to work. Java Plug-in 1.3 must be installed and each packaged JavaBeans consists of at least a JAR file, a TLB (Type Library) file and a REG (Registry) file. They must be reachable from the target machine, and the settings in the REG file should be imported into the target machine's registry. Note: The REG file contains the path of the JAR file and TLB file. If you move the JAR and TLB files to different locations on different machines, make sure the corresponding registry settings are updated accordingly. Internet Explorer SupportStarting with version 3.0, Microsoft Internet Explorer supports ActiveX components that can be downloaded and run within an HTML page. The Java Plug-in can be used to run Java Applets or JavaBeans components inside IE 3.0 using all the features of JDK 1.1. To use the Java Plug-in in Intenet Explorer, the bridge can be used as it is used in Visual Basic:
The JavaBeans component (JAR file, type library and registration) will have to be installed on each target machine using either a custom installation or technologies like CAB files (see CAB SDK from Microsoft). Alternatively, the bridge is able to support non-registered JavaBeans components on a target machine if the information about the JavaBean is stored in the properties of the ActiveX control (using the PARAM tags). For that, the bridge uses a unique CLSID, (the generic CLSID of the bridge) that allows it to run in any ActiveX container application, but not to run any particular JavaBeans component. Please refer to the Java Plug-in HTML Specification. How to Script AppletsYou can use scripting in Java Plug-in applets. Currently, you can do scripting only for applets running in Internet Explorer. This document assumes that you understand the HTML tags required for Java Plug-in. Please refer to the Java Plug-in HTML Specification for more information on these tags. You also should be familiar with the scripting languages. A script, represented by a special script tag within the HTML document, invokes methods that have been implemented in the applet's Java program. Using scripting, you have the capability to call applet methods from within the HTML page. There are two scripting languages that you can use for scripting Java Plug-in applets:
In addition to invoking a method on an applet, you can also use scripts to:
Using Scripts to Invoke a MethodYou often want to use scripts to invoke methods on an applet. For example, you might have an HTML button that, when clicked, starts an animation sequence. You do this through a combination of HTML tags and scripting in the HTML file, plus the actual code in the applet itself. You need to include the following in your applet's HTML page:
These tags are explained in the following sections. Specify the AppletYou must designate an ID parameter within the OBJECT tag for your HTML page. Recall that the OBJECT tag includes such parameters as classid, width, height, and so on. The ID parameter is the symbolic name of the applet. Once you establish a symbolic name for an applet through the ID parameter, you can reuse this name later in the scripts to refer to this applet. For example, suppose you have an applet called Fractal. You add the ID parameter to the OBJECT tag and set ID to the symbolic name of the applet. You might set the tag as follows: ID="Fractal" Now, you can use the name Fractal within scripts to refer to the Fractal applet. Using the same Fractal applet example, your HTML page would begin with a FORM tag, followed by an OBJECT tag, that together might look as follows:
Associate the Action to the ScriptThe HTML page defines components that are intended to invoke actions triggered by the user. You use the INPUT tag to define these components. You specify the TYPE of the component, such as button, its NAME, and VALUE. To have the button or other component actually invoke the intended action, you need to add tags that specify:
For example, suppose your HTML page creates a button that, when clicked, starts a particular animation sequence. Your HTML tag creates the button and gives that button a name and a value. To do this you want to add two tags. One tag indicates that on a certain action, such as click, a corresponding script method should be called. You might have the tag onClick="method name". The method name is a script method within the same HTML page. You also want to use the language tag to specify the script's language. The language can be either VBScript for Visual Basic script, or JScript for JavaScript. Thus, you might have the following in your HTML page: <input type="button" name="Button1" value="Start" onClick="startVBFractal" language="VBScript"> This INPUT tag creates a button, names the button "Button1", and gives it the value "Start". It also specifies the scripting method that will be called when a user clicks the button, and the scripting method's language. In this example, the scripting method is startVBFractal, and the scripting language is VBScript. When the user clicks this button, the HTML page branches to the script method startVBFractal, which is written in Visual Basic script. The Script Tag and MethodYou must include a SCRIPT tag for the method that the onClick tag specified. The SCRIPT tag must have the same name as the name used in the onClick tag. It also has a parameter that specifies the script language. More importantly, the script method calls the Java applet method. It identifies the method by using the name of the applet as specified by the ID tag, followed by the actual method name as implemented in the applet code. For example, the same HTML page might have the following SCRIPT tag:
This example SCRIPT tag begins by specifying that the scripting language is Visual Basic. This is followed by the VBScript sub statement, which starts the definition of a scripting method. The sub statement supplies a label or name for the scripting method, calling it startVBFractal. This name must match the method name given for the input component's action parameter. For this example, both the onClick parameter and the sub statement specify the identical scripting method. The scripting method startVBFractal merely calls the actual method, startFractal, implemented in the applet code. It qualifies the method name by using the form name, then the applet name, then the method name itself, as follows: document.Form1.Fractal.startFractal() Example with JavaScriptAs mentioned earlier, you can also use the JavaScript language to script your Java applets or JavaBeans components running inside the Java Plug-in in Internet Explorer. The following example shows a JavaScript code setting the Label property on the ExplicitButton JavaBeans component (available from the Beans Development Kit).
<SCRIPT LANGUAGE "JavaScript" FOR="window" EVENT="onLoad()">
ExplicitButton1.setLabel("Don't Press Me !")
</SCRIPT>
Using Scripts to Catch EventsYou can also use scripts to catch events thrown by JavaBeans components. Only JavaBeans components can raise ActiveX events while running within the Java Plug-in 1.3. If your component is a Java applet and you wish to raise ActiveX events, you need to add a bridgeevents PARAM in your OBJECT tag that has the value "yes" to force the Java Plug-in to raise ActiveX events. This assumes that your Java applet has been programmed using the JDK 1.1 AWT event mode. In this example, it is assumed that the JavaBeans component has implemented the most recent JDK AWT event-handling interface. You need to include the following in your applet's HTML page:
The example that follows illustrates a JavaBeans component that has implemented the AWT event-handling interface. This HTML page puts up a button on the screen and waits for a button action. When the user clicks the button, it triggers an event which the JavaBeans component catches. There is a scripting function that invokes the code implemented on the JavaBeans component and, when the event occurs, the scripting function displays a message. The key parts of the HTML page follow. First, you have the OBJECT tag, which in our example looks as follows:
To begin with, you must specify the symbolic name of the script function in the ID parameter to the OBJECT tag. In this case, the name of the function is ExplicitButton1: <OBJECT ID="ExplicitButton1" Also, with the OBJECT tag, include a parameter that indicates that this is a JavaBeans component. This is accomplished by the following line: <PARAM NAME="type" value="application/x-java-bean;version=1.1">
You must be sure to declare the script function itself. This begins with the SCRIPT LANGUAGE tag that indicates the scripting language. In this example, the language is VBScript.
Define the script function starting with the Sub tag. The name of the script function must match the name used in the ID parameter, ExplicitButton1. In the example above, the function name also references the actionPerformed AWT method and passes it an action event parameter. When the event occurs, the scripting function will display a window alert and the message "OK !". Example with JavaScriptTo catch events using the JavaScript language, the remarks above about the OBJECT tag parameters are still valid, the change is reduced to the scripting code actually catching the event.
Java Plug-in ActiveX Capabilities--Technical DetailsThe Java Plug-in for Internet Explorer on Windows runtime is implemented using the COM threading model. When you run several JavaBeans components inside a multi-threaded ActiveX container (currently only Internet Explorer), each JavaBeans component is likely to run in a separate thread. If your Beans are making direct connections or sharing objects it's probably a good idea to think about concurrent access. Runtime EnvironmentAt runtime, the Java Plug-in does not need any particular CLASSPATH or PATH settings; the Registry is used to get all necesary information the bridge might need. The registry key used by the Java Plug-in are: HKEY_LOCAL_MACHINE\\Software\\JavaSoft\\Java Plugin\\1.1\\JavaHome This key refers to the installation directory of the bridge where it should find the .class it needs. If you choose not to set this key, you must set the CLASSPATH. The Java Plug-in will use by default the JRE with which it was installed (currently 1.1.6). By using the Java Plug-in Control Panel, you can specify an alternate JDK or JRE to use. If the Java Plug-in cannot load the selected JRE, it will always revert to the default JRE. If the default has been manually removed, it will try to use the PATH to find the JDK; if this fails, the Java Plug-in will fail to load. Persistent StorageIn order to run successfully on the ActiveX bridge, a JavaBeans component must be serializable through either serialization or externalization. The current interfaces supported by the bridge are IPersistStorage, IPersistStreamInit, and IPersistPropertyBag. When a JavaBean is asked to serialize itself, it must perform all serialization in one thread. The bridge may choose to persist the JavaBean through textual property persistence. All public properties will be persisted though the values the accessor methods return. If a particular property is a Java Object, the PropertyEditor getAsText/setAsText methods will be used. If they are not implemented, serialization will be used on the property. As stated for Code Generation in the JavaBeans specification version 1.01, The JavaBean designer may specify that a JavaBean cannot be restored by simply saving and restoring its properties. This can be done by using the Feature Descriptor's attribute/value mechanism (see the JavaBeans specification paragraph 5.4.1). If the JavaBean descriptor property "hidden-state" is set to true, the JavaBean will always be persisted through serialization or externalization. EventsAll source interfaces that are declared as default in the EventSetDescriptor array returned by the BeanInfo will be merged into one interface which is declared as being the ActiveX default source interface. It is an ActiveX requirement that at least the default source interface is accessible by ActiveX containers. Each method returned by the getListenerMethodDescriptors API of the EventSetDescriptor is mapped to an ActiveX event. he event name is the method name. Consider, for example the java.awt.event.ActionListener source interface:
The ActiveX event name generated from this interface definition is actionPerformed. Since all default interfaces of your JavaBean are merged to a unique interface, do not use interfaces that contain the same method name. The new AWT event model specifies that all event notifications come with a unique event object containing all information describing the event. Although this is required, the event object fields should be immutable. This is an example of the event signature: Private Sub ExplicitButton1_actionPerformed (ByVal ActionEvent1 As Object) End-Sub The ActionEvent1 is an Automation object that can be used from any scripting environment to get information on the event. Note for the JavaBeans bridge for ActiveX users: In the 1.0 release of the JavaBeans bridge for ActiveX, users had the choice between cracking or uncracking events. This feature has disappeared in the 1.1 release. PropertiesAll properties are accessible though the bridge with the same access right as defined in the PropertyDescriptor. The ActiveX bridge will automatically invoke the accessor methods defined in the PropertyDescriptor. If the property is bound or constrained, the [bindable] or [requestedit] flags are set in the description of the OLE property. The IPropertyNotifySink interface will forward the PropertyChangeEvent. If the OLE container denies the property change and the property is constrained, the PropertyVetoException is thrown by the bridge. Native properties will be mapped to their OLE type as described below: Table 5.1: Java to Automation Mappings
Note: Arrays of multiple dimension are not supported in this release. All property names will have their first letter recapitalized for consistency with ActiveX conventions (label becomes Label). For simple types and string, font, and color, most ActiveX containers like Visual Basic will allow direct manipulation of the properties in their PropertySheet. For all other properties like Arrays or Objects, the properties will not be accessible in the PropertySheet but can still be invoked using the scripting language offerred by the container. MethodsAll methods declared in the BeanInfo via a MethodDescriptor will be automatable from OLE Automation-capable containers. Overloaded methods are currently not accepted by automation; the bridge will use name mangling (repaint, repaint2, repaint3... use a type library browser to find which overloaded method you wish to call). Please note that the bridge currently does not support static methods. Arguments and return values are automatically marshalled by the bridge (refer to Table 5-1 for translation values). Exceptions thrown by the method will be caught by the bridge, packaged in the EXCEPINFO structure and returned to the OLE container. Ambient PropertiesThe bridge supports four ambient properties that get translated to the JavaBeans properties if the JavaBeans component implements these properties. These ambient properties will be read and set on the JavaBeans component when the component is first painted on the canvas (InitNew) and each time a change notification for the ambient properties is received. Properties that map standard control properties are shown below. Table 5.2: Standard DISPID Assignment
ActiveX container ambient property changes of the previous types will be forwarded by the bridge to the JavaBean via a property set on the property. IntrospectionIntrospection is not used at runtime, only at packaging time. However, in Internet Explorer for Java applets or JavaBeans components that do not have a dedicated CLSID, introspection will be used. All methods and properties will be accessible as described earlier. With Java Plug-in 1.3, only the source interfaces that are declared as being part of the default set will be packaged as a unique ActiveX source interface. CustomizationCustomizers, when defined, are available at design time in Visual Basic though the Property pages of the component or by invoking the menu item Properties by right-clicking on the JavaBeans component. PackagingThe Java Plug-in supports JavaBeans packaged in JAR files only. The packager will add a stub .class file in this JAR file. You can still use the JAR file once packaged with the Beanbox application on any platform if the classpath includes the bridge Java classes (sun.beans.ole.*). Registry FileThe packager will generate the type library file (repository of the capabilities of the JavaBean) and the registry file. The registry indicates the executable location, the type library location, and other information. You may edit the registry file. Register the registry file as follows: regedit FileName.reg Contained in the registry file is information about the executable location. This is where you have copied the beans.ocx file. One beans.ocx is enough to run all the packaged JavaBeans. You don't need to duplicate this .ocx file for each JavaBean.
[HKEY_CLASSES_ROOT\CLSID\{23BE13F0-4B64-11CB-BB1D-00805F2ADE08}\InprocServer32]
@= "c:\\perso\\beans\\beans.ocx"
The registry file has at least three lines of information as shown below:
Here is the location of the bitmap and the icon for the ocx. Use a gif->ico or gif->bmp translator program to move your gifs to Windows-specific format and put the path for these files here. If you want to load them from an executable, follow the example below where 1 is the ResourceID for the bitmap.
[HKEY_CLASSES_ROOT\CLSID\{23BE13F0-4B64-11CB-BB1D-00805F2ADE08}\ToolboxBitmap32]
@= "g:\\workspaces\\bridge\\classes\\beans.ocx,1"
[HKEY_CLASSES_ROOT\CLSID\{23BE13F0-4B64-11CB-BB1D-00805F2ADE08}\DefaultIcon]
@= "g:\\workspaces\\bridge\\classes\\hotjava.ico"
Here is the location of the type library generated by the packaging step. Change this information only if you move files around.
Advanced Automation UsageArray ManipulationIndexed properties and other arrays are accessible through the bridge as SafeArrays. Arrays of all types (except Java long) can be obtained or passed to a Java component from any OLE-compliant scripting environment. Here is an example of how to retrieve an array of short from a hypothetical JavaBeans property called ShortArray and display all its values in a Visual Basic Dialog Box:
Indexed properties can also be set using an index and a value or by setting the entire array in one property set. Let's examine examples of the two methods:
Object CreationTwo methods allow you to create new Java objects from any scripting facility. These methods are accessible from all Java objects visible in the scripting environment but not the JavaBean itself. This means that any object that a JavaBean returns as a result of a method invocation (for example, a property get or event fire) supports these methods. The first method, getNew, takes one argument of type string that identifies the class name of the object you want to instantiate. The GetNew implementation will try to load the class using the system classloader and instantiate it using the newInstance method of the Class class. Here is an example in Visual Basic of creating a new Button inside an actionPerformed event listener method implementation:
The second method for creating new Java objects is getConstructor and is provided as part of the JDK1.1 reflection APIs. Using the reflection APIs, one can obtain the list of constructors for a particular class and then can invoke one of these constructors using the Method.Invoke API. getConstructor takes two arguments of type string; the first argument is the class of the object, the second argument is a list of parameters delimited by semi-colons (;). Refer to the JDK 1.1 reflection API documentation for a complete reference. The bridge will try to find a constructor that satisfies the following pattern : public arg1(arg2); where arg1 and arg2 are the arguments of the getConstructor method. For example, in the java.awt.Button class definition, you will find the constructor:
The object returned by the getConstructor method is either null if the constructor cannot be found following the design pattern described above, or an IDispatch reference on the Method object (see java.lang.reflect.Method). You can use this method object to create a one to many instances of the class you need by invoking the newInstance method on it. If you look in the class java.lang.reflect.Constructor, you'll see that the newInstance method takes an array of Object as the list of parameters to be passed to the constructor. Here is an complete example of how to invoke the Button constructor described earlier:
Direct Connections Between JavaBeansIt is possible to make direct connections between JavaBeans running in the bridge inside the same application. This requires a script for the initial hookup but once accomplished, the two components communicate directly without going through the bridge or COM. This will allow a JavaBeans component to directly receive events of other JavaBeans components running in the same container without paying the price of the bridge and the COM layers. Consider a JavaBean that implements the java.awt.event.ActionListener interface to receive button events. To do so, the JavaBean can directly implement the listener interface or much more cleanly provide an adaptor class that implements the listener interface. The example below illustrates the latter approach using a new feature of JDK1.1--nested classes.
Invoking the getActionListener method on this JavaBean returns an object that implements the ActionListener interface. The interface implementation actionPerformed method creates a new dialog box to notify the user that the ActionEvent has been received. The ExplicitButton JavaBean that is delivered as part of the Beans Development Kit sources the ActionListener interface. You can link the interface implementation of the first JavaBeans component to an ExplicitButton instance of get the dialog box to pop up when the user presses the button. The hookup can be done when the Visual Basic form is loaded:
Private Sub Form_Load()
ExplicitButton1.addActionListener(JavaBeans1.getActionListener)
End Sub
If the JavaBeansExample component directly implements java.awt.event.ActionListener, the code would look like:
And the method hookup would be :
Private Sub Form_Load()
ExplicitButton1.addActionListener(JavaBeans1.Object)
End Sub
Either approach is valid. When the user presses the JavaBeans ExplicitButton, the event is caught by the JavaBeanExample component which then displays a dialog box. These direct connections are not limited to events. An object created by one JavaBeans component can be passed as a method parameter to another JavaBean. Note that the original object is passed and not a copy. Direct Connection in Internet ExplorerThe same direct connection can also be set up while running inside Internet Explorer. The following code which is executed when Internet Explorer fires the Window onLoad event (all components in the page are loaded), demonstrates the same hookup between the two components in the previous example.
OLE Automation ServerIt is possible to take a JavaBeans component and make it an OLE Automation Server (no UI). The JavaBeans Bridge for ActiveX has built-in support for this feature, so no change is needed in the JavaBeans component. Here is an example in Visual Basic of creating a new TickTock and invoking its methods through OLE Automation:
The result will be the following:
Unregister JavaBeans over ActiveXIn some cases, it is necessary to unregister a packaged JavaBeans component over ActiveX, so we provide two utilities for performing this task in DOS and Win32. UnregBean is a command prompt-based program. It takes the ProgID of the JavaBeans component to perform the unregistration. During JavaBeans packaging time, you are asked for an ActiveX name. The ProgID is normally the ActiveX name + ".Bean.1". For example, if the ActiveX name is Select, the ProgID should be "Select.Bean.1". UnregBean -h -d -i <ProgID> -u <ProgID>
The UnregBean displays output messages in the standard output of the command prompt. WUnregBean is a Win32-based utility for unregistration.
CLSID, ProgID, Version-Independent ProgID and the path of the JAR file are displayed. To unregister a JavaBeans over ActiveX, simply click the "Unregister JavaBeans" button, and the utility will perform the task. To remove the stubs in the JAR file during unregistration, UnregBean and WUnregBean require JDK 1.1 to be installed in the target machine. However, if JDK is not installed, UnregBean and WUnregBean will still unregister the selected JavaBeans, but stubs will not be removed from the JAR file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| ||||||||||||