BEA Home | Events | Solutions | Partners | Products | Services | Download | Developer Center | WebSUPPORT
| WebLogic Server Doc Home | WebLogic jCOM User Guide | Previous Topic | Next Topic | Contents | View as PDF

Programming

WebLogic jCOM uses the Windows Distributed COM (DCOM) network protocol to provide communication between both local and remote COM components and a pure Java environment. The following sections describe what the programmer has to do in order to use WebLogic jCOM to access Java components from a COM client:

- Server-Side Programming Requirements

- Client-Side Programming Requirements

- Intercepting the Instantiation of Java Objects

- Instantiating Java Objects from COM using Constructors

- Implementing a Singleton Java Object

Server-Side Programming Requirements

The programming requirements on the server side are, for most programming models, limited to configuration and compiling and activating the bridge. When implementing an early bound programming model or a late bound encapsulation programming model you have to, in addition, generate wrappers and a type library.

The bridge file, JCOMBridge.java, is provided with the WebLogic jCOM installation. This file is used in all the examples provided and can be used as a base for creating your own bridge file, should you wish to do this.

To establish the bridge on the server side, the following needs to be done, irrespective of the programming model being implemented:

1. Start WebLogic Server.

2. Set the PATH environment variables to point to the root directories of your WebLogic Server and JDK 1.3 installations (by running the setEnv file).

3. Ensure that the WebLogic Server's listen port (7001 by default) is correctly specified by editing the following line in the bridge file:

   >     env.put(Context.PROVIDER_URL, "t3://localhost:7001")

4. Compile the WebLogic jCOM bridge file by executing the build script build.xml. You can do this by running the following command:

   >     ant

5. Configure the WebLogic jCOM environment, by setting the PATH environment variables to point to the root directory of your WebLogic jCOM installation.

6. Invoke the bridge on the server side by using the following statement which runs the bridge file, JCOMBridge.java:

   >     java -classpath %CLASSPATH% -DJCOM_DCOM_PORT=7050 JCOMBridge

   where 7050 is the port where the WebLogic jCOM bridge must listen for client-to-server communications.

   The bridge file, JCOMBridge.java, defines the WLS TCP/IP address and listen port and registers the JVM name with JNDI.

If you are implementing early binding or late bound encapsulation, the following additional steps are required:

1. Set up the generation environment needed for the execution of the java2com tool and compilation of the bridge and wrappers. The CLASSPATH needs to include a path to the jCOM.jar as well as a path to the Java classes being accessed.

2. Generate Java wrappers and an IDL file for your Java component with the java2com tool:

   >     java com.bea.java2com.Main

   When this line is executed, the java2com window will pop up. In the Java Classes & Interfaces field, you must enter the names of the classes you wish to use, including the bridge class.

3. Make sure that the generated classes and JCOMBridge.class file are in your CLASSPATH, then compile the Java wrapper files:

   >     javac Output Directory\*.java

Client-Side Programming Requirements

For the programing steps required on the client system, we will look at how to implement the following programming models:

- DCOM Zero Client Programming Model

- DCOM Late Bound Programming Model

- DCOM Early Bound Programming Model

- DCOM Late Bound Encapsulation Programming Model

- Native Mode Programming Model

DCOM Zero Client Programming Model

The basic client-side programming steps required to implement a DCOM zero client programming model are (described below for a VB client accessing an EJB on the WebLogic Server):

1. Generate a coded reference to the bridge's location (the objref) using the Java class com.bea.jcom.GetJvmMoniker. Specify as parameters the full name or TCP/IP address of the server machine and the port where the bridge can be accessed, for example:

   >     java com.bea.jcom.GetJvmMoniker mymachine.mycompany.com 7050

   or

   >     java com.bea.jcom.GetJvmMoniker localhost 7050

2. In the client source code, access the bridge using the following statement which contains the generated objref:

   >     Set objBridge = GetObject("objref:generatedobjref")

3. Following this, all objects can be requested from the server using JNDI, for example:

   >     Set objHome = objBridge.get("JVMName:jndi name of ejb")

DCOM Late Bound Programming Model

The basic client-side programming steps required to implement a DCOM late bound programming model are (described below for a VB client accessing an EJB on the WebLogic Server):

1. In the source code for the VB client, first link a COM object to an interface of the EJB. In this extract from a VB client's source code, notice the declaration of the COM version of the EJB's home interface, objHome. This COM object is linked to an instance of the EJB's home interface on the server side.

   >     Dim objHome As Object

   >     Private Sub Form_Load()

   >     'Handle errors

   >     On Error GoTo ErrOut

   >     'Bind the EJB's HomeInterface object via JNDI

   >     Set objHome = GetObject("JVMName:jndi name of ejb")

   GetObject is getting an object through JNDI lookup on the WebLogic Server. The JVM ("JVMName") needs to be registered in the registry, as described in step 3.

2. Any further references to this object appear to be referring to a COM object, but are in fact using the Java methods as if they are COM methods.

3. On the client system use the regjvm tool to register the local Java Virtual Machine by adding the name to the Windows registry and associating it with the TCP/IP address and client-to-server communications port where WebLogic jCOM will listen for incoming WebLogic jCOM requests. For example:

   >     regjvmcmd JVMName localhost[7050]

DCOM Early Bound Programming Model

The basic client-side programming steps required to implement a DCOM early bound programming model are (described below for a VB client accessing an EJB on the WebLogic Server):

1. Copy the generated IDL (see Server-Side Programming Requirements above) to the client system.

2. Compile the IDL file into a type library using the Microsoft IDL compiler midl.exe:

   >     midl generatedIDLFileName.idl

   The result of the compilation is a type library of the same name, but with the extension .tlb.

3. Register the type library and set the JVM it will service, for example:

   >     regtlb /unregisterall

   >     regtlb generatedIDLFileName.tlb JVMName

   The first line above calls regtlb.exe in order to un-register any previously registered type library versions. The second line then registers the newly compiled type library and specifies the name of the JVM ("JVMName") that will be linked with the type library. The WebLogic jCOM runtime requires this information for linking type library defined object calls to the appropriate wrapper classes.

4. Now the client can access the type library. Load the VB project and in the Projects menu, select Reference. Scroll down until you find the type library and activate its check box. Click OK.

5. Objects are no longer declared "As Object", but rather by using the type library:

   >     Dim objCOM As generatedIDLFileName.generated class name

   For example, if your fully qualified Java class is examples.ejb.basic.containerManaged.AccountHome, your generated class name would be ExampleEjbBasicContainerManagedAccountHome.

6. To access design time information about the various methods and properties of the objects, the following is also required:

   >     Dim objTemp As Object

   >     Dim objBridge As New generatedIDLFileName.COMtoWebLogic

   >     Set objTemp = GetObject("JVMName:jndi name of ejb")

   >     Set objHome = objBridge.narrow(objTemp,"fully qualified java
   >     class")

   Notice the objTemp object uses a late bound method to obtain a reference to the EJB object. This late bound object is passed to the bridge's "narrow" method, and is given an early bound object in return.

7. On the client system use the regjvm tool to register the local Java Virtual Machine by adding the name to the Windows registry and associating it with the TCP/IP address and client-to-server communications port where WebLogic jCOM will listen for incoming WebLogic jCOM requests:

   >     regjvmcmd JVMName localhost[7050]

DCOM Late Bound Encapsulation Programming Model

Using late bound encapsulation allows you to retain the majority of the benefits of early bound programming, while implementing a more flexible late bound model that does not require wrappers or type libraries.

For example, if you have a Visual Basic client accessing an EJB, you will need to do the following:

1. Copy the generated IDL (see Server-Side Programming Requirements above) to the client system.

2. Compile the IDL file into a type library using the Microsoft IDL compiler midl.exe:

   >     midl generatedIDLFileName.idl

   The result of the compilation is a type library of the same name, but with the extension .tlb.

3. Register the type library and set the JVM it will service, for example:

   >     regtlb /unregisterall

   >     regtlb generatedIDLFileName.tlb JVMName

   The first line above calls regtlb.exe in order to un-register any previously registered type library versions. The second line then registers the newly compiled type library and specifies the name of the JVM ("JVMName") that will be linked with the type library. The WebLogic jCOM runtime requires this information for linking type library defined object calls to the appropriate wrapper classes.

4. Reference this type library from within a Visual Basic project, using the Project->References dialog.

5. Add an empty class module to the project and open its source window.

6. Add a module level variable of type "Object" that will be used to reference your EJB.

7. Using the "object" and "procedure" pull-down menus at the top of the class module's source window, add a Class_Initialize method, and place within the method the source code required to assign your module level object variable a reference to your EJB. See DCOM Late Bound Programming Model for the necessary initialization source.

8. Use the Implements keyword at the top of your class source to implement the interface of any objects you'll need to access. You can reference your EJB objects using the name of your type library, followed by a dot. (i.e. Implements generatedIDLFileName.generated class name)

   For example, if your fully qualified Java class is examples.ejb.basic.containerManaged.AccountHome, your generated class name would be ExampleEjbBasicContainerManagedAccountHome.

9. Use the "object" and "procedure" pull-downs to select all of the methods and properties from the EJB objects that you'll need to access. This should produce the skeleton source code for the selected methods and properties.

10. Within these method and property declarations, insert late bound code that accesses the EJB's methods and properties through the module level object you've created.

11. Delete the "Implements" entries from the top of your class source, and remove the type library reference from the Project->References dialog. Your class no longer depends on the type library (and hence, the wrappers on the server) for access to the EJB.

Once you have done this, you can instantiate an instance of the class you've created, and access all of your EJB functionality as though it were early bound. Any changes to the EJB will not affect your VB project so long as the interface remains static for the methods and properties employed in the VB client source.

Native Mode Programming Model

In native mode a COM client accesses a Java object running on the same machine as the client. WebLogic jCOM uses native code to facilitate the interaction. For more on native mode see Native Mode in the Reference Guide.

Intercepting the Instantiation of Java Objects

If you wish to control the instantiation of Java objects, create a class which implements the com.bea.jcom.Instanciator interface. This interface has one method, which looks like this:

>     public Object instanciate(String javaClass) throws
>     com.bea.jcom.AutomationException;

Pass a reference to your instantiator as a second parameter when calling Jvm.register(...):

>     com.bea.jcom.Jvm.register("MyJvm", myInstanciator);

The default instantiator used by WebLogic jCOM looks like this:

>     public final class DefaultInstanciator implements
>     com.bea.jcom.Instanciator {
>     public Object instanciate(String javaClass)
>     throws com.bea.jcom.AutomationException {
>     try {
>     return Class.forName(javaClass).newInstance();
>     } catch(Exception e) {
>     e.printStackTrace();
>     throw new AutomationException(e);
>     }
>     }
>     }

For example this is a VB to EJB bridge (based on Sun's JNDI Tutorial):

>     import javax.naming.*;
>     import java.util.Hashtable;
>     import com.bea.jcom.*;

>     public class VBtoEJB {
>     public static void main(String[] args) throws Exception {
>     Jvm.register("ejb", new EjbInstanciator());
>     Thread.sleep(10000000);
>     }
>     }

>     class EjbInstanciator implements Instanciator {
>     Context ctx;

>     EjbInstanciator() throws NamingException {
>     Hashtable env = new Hashtable(11);
>     env.put(Context.INITIAL_CONTEXT_FACTORY,
>     "com.sun.jndi.ldap.LdapCtxFactory");
>     env.put(Context.PROVIDER_URL, "ldap://... TBS ...");
>     ctx = new InitialContext(env);
>     }

>     public Object instanciate(String javaClass) throws
>     AutomationException {
>     try {
>     try {
>     return Class.forName(javaClass).newInstance();
>     } catch(Exception e) {}
>     return ctx.lookup(javaClass);
>     } catch (Throwable t) {
>     t.printStackTrace();
>     throw new AutomationException(new Exception("Unexpected: " + t)); }
>     }
>     }

If you compiled the above, and ran it on a machine (development.company.com) like this:

>     java -DJCOM_DCOM_PORT=4321 VBtoEJB

Then on a Windows machine you used the WebLogic jCOM regjvmcmd command like this:

>     regjvmcmd ejb development.company.com[4321]

Then from VB you would then use:

>     Set myEjb = GetObject("ejb:cn=ObjectName")
>     MsgBox myEjb.someProperty
>     myEjb.myMethod "a parameter"

Instantiating Java Objects from COM using Constructors

COM has no concept of constructors. One method is to define a default constructor, and then define a static member which takes the appropriate parameters and instantiates the object and returns it:

>     public class MyClass {
>     	public MyClass() {}
>     	public MyClass(String p1, int p2, double p3) {
>     	...
>     	}

>     public static MyClass createMyClass(String p1, int p2, double p3) {
>     	return new MyClass(p1, p2, p3);
>     }
>     }

Another possibility is to use WebLogic jCOM's instantiation interception capability -- when you register the JVM you can pass a reference to an object whose class implements a special Java jCOM interface which is called when you use GetObject("MyJvm:MyClass") -- you get passed everything after the colon, so you could actually do: GetObject("MyJvm:MyClass(1, 2, three, 4.0") and then in the interceptor parse the string that is passed in, and invoke the appropriate constructor.

Implementing a Singleton Java Object

In COM terminology an object is a singleton if there exists only one instance of the object at any time. Each time you call CreateInstance you obtain a reference to the same object. This ensures that all clients access the same instance.

By controlling the instantiation of Java objects you can implement a singleton Java object which is accessible from COM clients. Here is an example of what the instantiator would look like for a class called mySingletonClass:

>     import java.util.*;
>     import com.bea.jcom.*;

>     public class COMtoJava {
>     public static void main(String[] args) throws Exception {
>     try {
>     Jvm.register("MyJvmId", new
>     SingletonInstanciator("MySingletonClass"));

>     while (true) { // wait forever
>     Thread.sleep(100000);
>     }
>     } catch (Exception e) {
>     System.out.println(e.getMessage());
>     e.printStackTrace();
>     }
>     }
>     }

>     class SingletonInstanciator implements Instanciator {
>     String singletonClassname;
>     static Object singletonObject = null;

>     SingletonInstanciator(String singletonClassname) {
>     try {
>     this.singletonClassname = singletonClassname;
>     if (singletonObject == null) {
>     System.out.println("SingletonInstanciator: creating the singleton
>     [" + singletonClassname + "]");
>     // initialize the singleton
>     Class classObject = Class.forName(singletonClassname);
>     singletonObject = classObject.newInstance();
>     }
>     } catch (Exception e) {
>     System.out.println(e.getMessage());
>     e.printStackTrace();
>     }
>     }

>     public Object instanciate(String javaClass) throws
>     AutomationException {
>     try {
>     System.out.println("instanciate for " + javaClass);

>     // if request is to create the singleton, just return the existing
>     instance.
>     if (javaClass.equals(singletonClassname)) {
>     return singletonObject;
>     } else {
>     Class classObject = Class.forName(javaClass);
>     return classObject.newInstance();
>     }
>     }
>     catch (Exception e)
>     {
>     System.out.println("Failed to instanciate class " + javaClass);
>     System.out.println(e.getMessage());
>     e.printStackTrace();
>     System.out.println("Throwing exception back to caller.");
>     throw new AutomationException(e);
>     }
>     }
>     }

And here is a sample MySingletonClass implementation:

>     public class MySingletonClass {
>     public MySingletonClass() {
>     System.out.println("MySingletonClass constructor called.");
>     }

>     public int Method1(int val) {
>     return val + 1;
>     }
>     }

If you compiled both of the above, and ran COMtoJava on a machine (development.company.com) like this:

>     java -DJCOM_DCOM_PORT=4321 COMtoJava

Then on a Windows machine you used the WebLogic jCOM regjvmcmd command like this:

>     regjvmcmd MyJvmId development.company.com[4321]

Then from VB you would then use:

>     Set objMySingleton1 = GetObject("MyJvmId:mySingletonClass")
>     Set objMySingleton2 = GetObject("MyJvmId:mySingletonClass")
>     MsgBox objMySingleton1 & objMySingleton2

Which would create two references to the same object.

Copyright © 2001 BEA Systems, Inc. All rights reserved. Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.