Reverse COM (Implementing COM Servers in Java)

jSegue contains support code to help you create in-process COM servers in Java. You can create your Java objects by implementing interfaces that have been generated with tlb2java. Then, you can register your Java servers with COM so that non-Java clients can create and use your Java COM objects. jSegue supports both Java and COM aggregation so that you can use the services of existing Java or COM code to implement your COM objects. Note that type library information must be available at run-time for reverse COM to work. Currently we have only implemented vtable support, so clients that use IDispatch to call into [dual] servers will not work.

In order, to create a Java COM object server your class must extend com.moesol.bindings.platform_sdk.component_services.ComObject. Furthermore, it must declare a public static field of type GUID named CLSID. It may optionally, declare a public static field of type String named PROGID It may optionally, declare a public static field of type GUID[] named IMPLEMETNED_CATEGORIES. For example,

public class MyVtableServer extends ComObject implements IDual, IDispOnly { 
    public static final GUID CLSID = GUID.fromString("4C31CCCB-E47F-4466-8D24-46FCEAB5AD65");
    public static final String PROGID = "MyVtableServer.1";
    public static final GUID IMPLEMENTS_CATEGORIES[] = { 
       GUID.fromString("08C53E19-AEEB-437D-A4E2-5545EF7BE507"), 
    };
    //...

Then, you need to implement the interface methods of the interfaces you implement. To make your COM server available outside of Java you need to register it with COM. jSegue provides a helper method:

com.moesol.bindings.platform_sdk.component_services.ComRegistryHelper.registerServer(Class java_class, String group_name);

registerServer uses the static fields CLSID, PROGID, and IMPLEMENTED_CATEGORIES to register your Java COM server with COM. PROGID and IMPLEMENTED_CATEGORIES are optional. For example,

/**
 * Trivial main to register this server.
 * 
 * @param args
 */
public static void main(String[] args) {
    NativeLibraryLoader.loadLibrary("com_moesol_bindings");
    COM.registerServer(MyVtableServer.class, "com.moesol.test.group");		
}

registers MyVtableServer with COM. For those familiar with COM or interested in the details, below is an example of the Windows registry keys that get added:

HKEY_CLASSES_ROOT\CLSID\{4C31CCCB-E47F-4466-8D24-46FCEAB5AD65}
HKEY_CLASSES_ROOT\CLSID\{4C31CCCB-E47F-4466-8D24-46FCEAB5AD65}\Implemented Categories
HKEY_CLASSES_ROOT\CLSID\{4C31CCCB-E47F-4466-8D24-46FCEAB5AD65}\Implemented Categories\{08C53E19-AEEB-437D-A4E2-5545EF7BE507}
HKEY_CLASSES_ROOT\CLSID\{4C31CCCB-E47F-4466-8D24-46FCEAB5AD65}\InProcServer32
	[<default>]=C:\wk\jSegue\src\lib\com_moesol_bindings\Debug\com_moesol_bindings.dll
	[Class]=com.moesol.bindings.platform_sdk.component_services.MyVtableServer
	[Group]=com.moesol.test.group
HKEY_CLASSES_ROOT\MyVtableServer.1
	[<default>]=MyVtableServer
HKEY_CLASSES_ROOT\MyVtableServer.1\CLSID
	[<default>]={08C53E19-AEEB-437D-A4E2-5545EF7BE507}

The Class and Group values are specific to jSegue. Class is used at run-time to bind the Java class to the COM clsid. Group is used at run-time to bind the Java class to a Java ClassLoader. By placing multiple Java classes into the same group you can make them work together. Conversely if two Java classes are in different groups then they will not be able to see each others static data because they will be loaded by different ClassLoaders.

Each Group will have its own class path. The class path is specified using system or user Preferences. Use system preferences if the component is registered for us by all users on the system, use user preferences if the component should only be available to the current user. The full path to the group's class path for this example is:

HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs\com\moesol\bindings\platform_sdk\component_services\com_inproc_groups\com.moesol.test.group\classpath
	[100.my.path]=c:\my\path
	[200.my.2nd.path]=c:\my\2nd\path.jar

Under the classpath key, you then place a value for each class path entry you want. The value names are sorted when building the class path so you can control the order or jars and directories by naming the values appropriately. Your code can use the java.util.prefs.Preferences API to create these registry keys, or you might choose to add them using your installation software.

Classes that use the Java Native Interface (JNI) should be loaded by the same classloader. Therefore you should register these classes so that the jSegue system classloader is used. You can use the special group com.moesol.system.group to add class path entries to the jSegue system class loader that is the parent classloader for all groups.

jSegue also supports configuring the java.util.logging package. Since the logging configuration is shared by the entire Java Virtual Machine you cannot configure the logging on a per-group basis. Instead, create a file in the same directory as the hosting executable. The file should have the same name as the hosting executable, but with a .properties file extension. This file should be in the java.util.Properties format. jSegue configures the logging subsystem to read this file for its logging configuration.

!
! Logging properties are merged with this file.
!
handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler,com.moesol.bindings.platform_sdk.debugging_and_error_handling.EventLogHandler
!.level= FINEST
.level= FINE
java.util.logging.FileHandler.level = FINE
java.util.logging.FileHandler.pattern = C:/gw-sample%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 2
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
		

$Id: index.html 4954 2007-10-29 05:31:43Z hastings $