The COM2JAVA Tool

The com2java tool generates Java "proxy" classes and interfaces that correspond to the coclasses and interfaces contained in a COM type library. It effectively generates a Java API which you can use to access a COM component from Java.

What Is a Type Library?

A type library is a binary file that describes a COM component's methods, properties, and data structures. Type libraries are compiled from Interface Definition Language (IDL) files using the Microsoft MIDL compiler. Files that end with the extension .tlb or .olb are type libraries. But type libraries can also be embedded inside other file types, such as .exe files. For example, the type library for Microsoft Excel 2003 is embedded in EXCEL.EXE.

Contents

  1. Generating Java Proxy Classes
  2. Com2Java Options
    1. General Options
    2. Clash Prefix
    3. Method Options
    4. Conflicting Interface Methods
    5. Commandline-only Options
  3. Overview of Generated Files
    1. Enumerations
    2. Interfaces & Coclasses
    3. "Source" Interfaces (i.e. COM Events)

1. Generating Java Proxy Classes

The com2java tool comes in two forms:

  1. Graphical Version: %JINTEGRA_HOME%\bin\com2java.exe
  2. Command Line Version: %JINTEGRA_HOME%\bin\com2javacmd.exe (type com2javacmd /? for usage information)

When you start com2java.exe, the following dialog is displayed:

  1. Select the type library you wish to generate Java proxy classes for.
  2. Type a Java package name for the generated files (e.g. java.microsoft.excel).
  3. Select Options from the Settings menu to modify the way the proxy classes are generated. See below for details.
  4. Click Generate Proxies. You will be asked to select an output directory for the generated files.
  5. Click New to add another entry to the list of type libraries for which you are generating proxies. This allows you to generate Java proxy classes for multiple type libraries at the same time.

2. Com2Java Options

To view the com2java options, click Options. Once the Java proxy classes are generated for a particular COM type library, its corresponding package, output directory, and options are saved to com2java's configuration file.

The current set of options and type libraries can also be saved to an XML file by selecting Save Settings from the File menu. These saved options can then later be loaded by selecting Load Settings from the File menu, or specifying the desired XML file as a program parameter when launching com2java.exe.

For most COM type libraries, the following default options will be sufficient to generate Java proxy classes which compile without error (all other options should be deselected):

2.1 General Options

Option Definition Command Line (com2javacmd)
Generate Java AWT classes This option appears on the main window of the com2java tool. It tells com2java to generate the Java proxy classes as AWT classes. This option is required when generating Java proxy classes for an ActiveX control that will be embedded in a Java frame. If you will not be displaying the ActiveX control visually, do not use this option.

* Before you can use this option, you must register your ActiveX control on the machine where you are running com2java (eg, regsvr32 myOcxFile.ocx).
/AwtForOcxs
Prompt for names for imported tlbs Sometimes one TLB will import another TLB. If you are also generating Java proxy classes for the imported TLB, this option causes com2java to prompt you for their package name. See the Knowledge Base for more details. /ExternalTypelib [typelib]=[packagename]
Proxies retry on "0x80010001 - Call was rejected by callee" If a COM server is busy, you may receive the above error. This option ensures the generated code keeps trying the method call when this error code is received. /RetryOnReject
Only generate Dispatch interfaces Most COM interfaces are dual interfaces, which means they can be accessed via vtable pointers or IDispatch:Invoke(). However, a COM interface which is defined in its TLB as a dispinterface can only be accessed via IDispatch:Invoke(). By default, J-Integra® accesses COM interfaces via vtable pointers. This option tells J-Integra® to use IDispatch:Invoke() instead. /IDispatchOnly
Generate BeanInfo classes for ActiveX controls This option allows you to generate BeanInfo classes for COM components marked as controls in the registry. This enables you to use COM ActiveX controls as Java Beans in Java IDEs such as JBuilder and Sun One Studio. If you wish to package these classes into a JAR file, then you will need to create an appropriate manifiest and corresponding GIF files (see the generated beaninfo proxy classes for the names/locations of the GIF files). Please consult your Java IDE's documentation for specific information on deploying beans within its environment. In order to use this option, you must also have the Generate Java AWT classes option selected. /GenBeanInfo

2.2 Method Options

These options affect method names and parameters.

Option Definition Command Line (com2javacmd)
Generate Java-style (lowercase) method names The Java convention is that all method names start with a lowercase letter. Select this option to follow the Java convention. /UpperCaseMemberNames allows uppercase method names (default: lowercase)
Don't treat [in]* params as arrays If the input parameter is called by reference - [in]* - com2java converts it to an array of the given type. For example, if the input parameter is int*, com2java generates int[] as the Java type. This option tells com2java not to treat [in]* parameters as arrays. This means the input parameter cannot be modified by the COM component. /TreatInStarAsIn
Generate Arrays as Objects This option affects method parameters which are SAFEARRAYs. Rather than having the generated method parameter specify the specific array type, this option tells com2java to specify java.lang.Object instead. This is useful in situations where you want to pass a multi-dimensional array. The number of dimensions is not specified in the COM IDL for SAFEARRAYs, and if you don't use this option J-Integra® will assume you are passing a one-dimensional array and generate a corresponding prototype. For example, by setting this option and having com2java generate java.lang.Object instead of java.lang.String[], you are free to pass a 2D String array. Please note that this does not change what is actually passed over the wire (it is still an array). /ArraysAsObjects
Omit [restricted] methods Prevents generation of methods marked [restricted] in the typelib. /OmitRestrictedMethods

2.3 Clash Prefix

Option Definition Command Line (com2javacmd)
Clash Prefix If a method defined in a TLB clashes with a standard Java method (e.g. "getClass"), com2java will prefix the generated method name with a string. "zz_" is the default. /ClashPrefix [string] (default: "zz_")

2.4 Conflicting Interface Methods

When a coclass implements multiple interfaces that possess methods of the same name, J-Integra® must take special actions when generating proxies for these objects. These options control how these naming conflicts are resolved.

Option Definition Command Line (com2javacmd)
Implement interfaces that may conflict If a COM coclass implements multiple interfaces which contain methods with the same name, then deselect this option so that the generated Java proxy classes do not implement the conflicting interfaces. You can still access the conflicting interfaces using the generated getAsXXX() methods (see the generated comments for details). /ImplementConflictingInterfaces
Don't rename methods with same names By default, if com2java detects a naming conflict in a COM coclass, it will automatically rename one of the methods by prepending the Clash Prefix. This option overrides the automatic renaming. /DontRenameSameMethods
Rename conflicting methods that differ by return value This option tells com2java to rename interface methods when a COM coclass implements two (or more) interfaces where each interface has identical methods which differ only by return value (something which is allowed in COM but not in Java). The methods are renamed by prepending the interface name. /RenameConflictingInterfaceMethods
Reuse methods that have the same name This option tells com2java to reuse interface methods when a COM coclass implements two (or more) interfaces where each interface has identical methods. The generated Java proxy class implements just one of the identical methods. /ReuseMethods

2.5 Commandline-only Options

For Convinience, the command-line version of com2java provides several additional options that that the GUI does not.

Option Definition Command Line (com2javacmd)
N/A in com2java GUI version This option forces an error if proxy generation will overwrite files. /DontOverwrite
N/A in com2java GUI version The specified file contains the names of multiple TLBs, package names, and output directories for generating Java proxy classes for multiple TLBs at the same time. For example, a text file called msproxies.txt containing the following lines:

    C:\Program Files\Microsoft Office\Office10\EXCEL.EXE,excel,C:\java2msexcel\excel
    C:\Program Files\Microsoft Office\Office10\WINWORD.EXE,word,C:\java2msword\word

Could be used to generate the Java proxy classes for both MSExcel and MSWord at the same time, by running com2javacmd as follows:

    com2javacmd [options...] /MoreTlbs msproxies.txt

/MoreTlbs [fileName]

3. Overview of Generated Files

The com2java tool processes the following data types in COM type libraries:

3.1 Enumerations

If a TLB contains an enumeration, com2java will generate a Java interface containing constant definitions for each element in the enumeration.

3.2 Interfaces & Coclasses

A COM coclass implements one (or more) COM interfaces. In COM, it is the interface which defines methods and properties, not the coclass. However, you can only access a particular interface through the coclass which implements it. The com2java tool mimics this relationship between interfaces and classes when it generates Java proxy classes for a COM type library.

For each coclass defined in a TLB, com2java generates a Java class with the exact same name as the corresponding COM coclass. And for each interface that a coclass implements, com2java generates a Java interface with the exact same name as the corresponding COM interface. Com2java also generates a special "Proxy" class for each COM interface as well.

Internally, both IMyInterface.java and MyClass.java delegate the real work to IMyInterfaceProxy.java. This abstraction gives you a clean Java API with a one-to-one correlation between COM/Java interfaces and classes. This means the generated Java API is identical to the existing COM API for any given COM component. To demonstrate this, here is an example using Microsoft Excel...

Advanced Features

Other than looking up interface and class names, you generally don't need to worry about the contents of these files in order to use J-Integra®. If you wish to learn more about some of the more advanced features of the generated classes, the Knowledge Base is a good source of information.

One additional feature of the IMyInterfaceProxy class is the ability to access a particular COM interface using only the CLSID of the COM coclass which implements it. For example...

COM Interfaces: "Dispinterface" versus "Dual"

J-Integra® handles two kinds of COM interfaces:

  1. DISPINTERFACE, whose methods can only be accessed via IDispatch:Invoke
  2. DUAL INTERFACE, whose methods can also be invoked directly via vtable pointers.

By default, J-Integra® uses vtable pointers (i.e. early binding) to access COM interfaces. If the COM component you are accessing contains interfaces which are not dual interfaces, you will need to use the com2java Only generate IDispatch option when generating the Java proxy classes. This tells J-Integra® to use IDispatch:Invoke() (i.e. late binding) to access COM interfaces. See Early Binding (VTable) vs Late Binding (IDispatch) in the KB for more information.

3.3 "Source" Interfaces (i.e. COM Events)

COM events are generated by a special type of interface defined in a TLB as a [source] interface. COM coclasses that implement a [source] interface can subscribe to the events it defines. Since Java has a completely different event mechanism from COM, the com2java tool hides the COM mechanism from the Java programmer and presents the events using the standard Java protocol. To demonstrate how com2java does this, let's look at an example.

The Java to Excel Example, particularly the Bonus Step (subscribe to Excel events) is a good example to run if you wish to see J-Integra®'s event handling in action. If you are interested in knowing exactly what com2java generates in the Java proxy classes to facilitate the handling of COM events in Java, please read through the following example.

Event Generation with Microsoft Excel

This is the IDL definition for the Excel Application class. Note how it specifies the AppEvents interface as a source interface:
[
  uuid(00024500-0000-0000-C000-000000000046),
  helpcontext(0x00020001)
]
  coclass Application {
    [default] interface _Application;
    [default, source] dispinterface AppEvents;
};

The AppEvents interface defines the events that can be generated as methods implemented by the interface:
  [
  uuid(00024413-0000-0000-C000-000000000046),
  helpcontext(0x000200a9),
  hidden
]
  dispinterface AppEvents {
    properties:
        [id(0x0000061d), helpcontext(0x0001061d)]
        void NewWorkbook([in] Workbook* Wb);

        [id(0x00000618), helpcontext(0x00010618)]
        void SheetBeforeRightClick(
                        [in] IDispatch* Sh,
                        [in] Range* Target,
                        [in] VARIANT_BOOL* Cancel);

        etc...
};

Application.java contains the standard Java methods for adding or removing an EventListener:
public void addAppEventsListener(excel.AppEvents theListener) ... {...}
public void removeAppEventsListener(excel.AppEvents theListener) ... {...}

Since AppEvents is a [source] interface, AppEvents.java extends java.util.EventListener:
public interface AppEvents extends java.util.EventListener ... {
  public void newWorkbook  (excel.AppEventsNewWorkbookEvent theEvent) ... ;
  public void sheetBeforeRightClick (excel.AppEventsSheetBeforeRightClickEvent theEvent) ... ;
  etc...
}

Another Java event convention is that each of the methods in the interface should have a single parameter, which is an instance of a class derived from java.util.EventObject Java class. If you look at the SheetBeforeRightClick method in the COM IDL above, you will see that it takes three parameters. In order to comply with the Java convention, com2java generates an additional class for each method in an event interface, each holding the parameters to the method. For example, here is an clip from AppEventsSheetBeforeRightClickEvent.java:
public class AppEventsSheetBeforeRightClickEvent extends java.util.EventObject {
  public AppEventsSheetBeforeRightClickEvent(Object source) { super(source); }
  public void init(Object sh, excel.Range target, boolean[] cancel) {
    this.sh = sh;
    this.target = target;
    this.cancel = cancel;
  }
  etc...
}

One final Java event related convention is the use of an Adapter class which implements the event interface and provides empty default implementations for the methods in the interface. This allows developers to create a class which will subscribe to the event but not implement all of the methods in the interface. In the case of the AppEvents interface, com2java generates AppEventsAdapter.java:
public class AppEventsAdapter implements excel.AppEvents {
  public void newWorkbook  (excel.AppEventsNewWorkbookEvent theEvent)
		throws java.io.IOException, com.linar.jintegra.AutomationException {...}
  public void sheetBeforeRightClickEvent  (excel.AppEventsWorkbookPivotTableOpenConnectionEvent theEvent)
		throws java.io.IOException, com.linar.jintegra.AutomationException {...}
  etc...
}