Making callbacks to Java Objects from COM

If you pass a reference to a Java object as a parameter to a method call on a COM object, then the COM object can invoke methods back into the Java object.

Such callbacks will not work from Applets, unless appropriate permissions (ability to establish a ServerSocket) are granted.

IDispatch based access is explained next, followed by access through a specific interface, further below.

IDispatch based access -- all Java public members are effortlessly accessible

If a COM object accesses the Java object through the IDispatch COM interface (in VB terms, a late bound object), then all public methods and properties can be accessed. Not only can all public members be accessed, but also class members (statics) can be accessed.

There is no need to run the Java code through any special software. There is no IDL or registration required. Simply pass a reference to the Java object, and the COM object can immediately make callbacks to all public members.

Please note that J-Integra® does not enforce any security restrictions on such callbacks. This means that if you pass a Java object reference to a COM object, that COM object can pretty much do anything. This is a small example of what we mean:

Java caller to a COM object

import com.linar.jintegra.AuthInfo;
import pure2vb.TestClass;
public class VbExample {
public static void main(java.lang.String[] args) throws Exception {
TestClass testClass = new TestClass(new AuthInfo("domain", "user", "password"));
testClass.meth1(new VbExample());
}
public void callBack(String p1, int p2) {
System.out.println("Callback has been called, with " + p1 + " and " + p2);
}
public String toString() { return "An instance of VbExample"; }
}

COM object making callbacks into Java

Public Sub meth1(ByVal javaObj As Object)
MsgBox "javaObj is " + javaObj
javaObj.callBack "hello", 2345

Set javaObjClass = javaObj.getClass()
MsgBox "javaObj's class is " + javaObjClass

Set hashtableClass = javaObjClass.forName("java.util.Hashtable")
Set aHashtable = hashtableClass.newInstance

aHashtable.put "The key", 1234
MsgBox "The new Hashtable's toString method returns: " + aHashtable
End Sub

From the above you can see that the Visual BASIC code accesses the Java Object's Class, and from that it instantiates an instance of a completely new class - the Java Hashtable class. The default value associated with a Java object is whatever it's toString() method returns.

These are the message boxes that the Visual BASIC code displays:



J-Integra®'s COM to Java bridging has the potential of opening the whole world of Java's Enterprise APIs to Visual BASIC users. What is especially powerful is that there is no need to perform any registration, or create IDL or do anything. All public members are instantly available.

Specific COM interface based access

The com2java tool processes a type library, and for each COM Interface it finds in the type library, it generates a corresponding Java interface (and also a Java proxy class).

If your Java class implements a Java interface generated using com2java, then instances of your class can be accessed through the corresponding orginal COM interface.

IDL: Two COM interfaces, and a COM Class

This is some COM IDL. There are two COM Interfaces and one COM Class defined in it:
...
library IFDEMOLib
{
...
interface IMyInterface : IDispatch
{
[id(1), helpstring("method method1")] HRESULT method1(BSTR* aString, LONG* aNumber, BOOL aBoolean);
};

...
interface IMyClass : IDispatch
{
[id(1), helpstring("method aMethod")] HRESULT aMethod(IUnknown* p1);
};

...
coclass MyClass
{
[default] interface IMyClass;
};

};

COM Class, implemented in C++

The COM Class is implemented in C++. This is the implementation of MyClass::aMethod. It queries the object passed in, to see if it implements the IMyInterface COM interface, and if it does, it invokes the method1 method:
STDMETHODIMP MyClass::aMethod(IUnknown * p1)
{
IMyInterface* pIMyInterface = 0;
HRESULT st = p1->QueryInterface(IID_IMyInterface, (void**)&pIMyInterface);
if(st == S_OK) {
BSTR aString = SysAllocString(L"A String");
LONG aNumber = 33;
BOOL aBoolean = true;
pIMyInterface->method1(&aString, &aNumber, aBoolean);
pIMyInterface->Release();
}

return S_OK;
}

The Java Class, which implements one of the COM interfaces

If you use the com2java tool on the type library which contains the definition of the class and interfaces in the above COM IDL, specifying ifdemo as the package name, the IMyInterface Java interface is generated.

The following Java class implements that interface. The main method create an instance of the MyClass COM Class, and then invokes the MyClass::aMethod method, passing an instance of the Java Class as a parameter:
import com.linar.jintegra.AuthInfo;
import ifdemo.*;
public class InterfaceExample implements IMyInterface {

public static void main(java.lang.String[] args) throws Exception {
try {
AuthInfo authInfo = new AuthInfo("domain1", "joe", "joejoe");
MyClass myClass = new MyClass(authInfo);
Object aJavaObject = new InterfaceExample();
myClass.aMethod(aJavaObject);
} finally {
com.linar.jintegra.Cleaner.releaseAll();
}
}

public void method1(java.lang.String[] aString, int[] aNumber, int aBoolean) {
System.out.println("method1 called with '" + aString[0] + "'," + aNumber[0] + "," + aBoolean);
aString[0] = "a new string";
aNumber[0] = 88;
}
}

Results

These are the somewhat uninspiring results of running the example. The Java object invokes the COM object, which makes a callback to the Java object, via the IMyInterface interface:

The interface proxy Java class generated by com2java must be present

In order to allow methods in a specific COM interface to be invoked on a Java object, J-Integra® uses the interface Proxy class generated by com2java (in the case of the example above, the proxy is IMyInterfaceProxy, generated by com2java in IMyInterfaceProxy.java.

If this class is not present, J-Integra® generates the following warning (when logging is set to 1, meaning Errors):

For the curious, this is J-Integra®'s log, when logging is set to 2, meaning Brief. Unless you are well versed in the workings of DCOM, it probably won't mean much to you! (the interface proxy has been restored):