Now, let's go to the other side and develop a COM client in Java. This program invokes the service within the COM server that the system has installed. For the present example, we are using a client that was implemented for the server in the previous example. Although the code looks familiar in the eyes of the Java programmer, everything that happens behind the scenes is unusual. This example uses a Java-written server, but it can be applied to any ActiveX control, ActiveX Automation server, or ActiveX component that is installed in the system-as long as we have a type library.
First, we apply the JActiveX tool to the server's type library. JActiveX has a range of options and switches to choose from. But its most basic form is to read a type library and generate Java source files. This source file is stored in our Windows/java/trustlib directory. The following line of code applies to the type library that is generated for the external COM Automation server:
Jactivex/javatlb javaadder.tlb
After JActiveX is finished, let's take a look at our Windows/java/trustlib catalogue. At this point you can see a new subdirectory named Javaadder. This directory contains the source files for the new package. This is a library that is similar in Java to the functionality of a type library. These files need to use the Microsoft compiler's dedicated boot command: @com. JActiveX generates multiple files because COM uses multiple entities to describe a COM server (another reason is that I don't fine-tune the use of MIDL files and java/com tools).
A file named Adder.java is equivalent to a coclass boot command in a MIDL file: it is a declaration of a COM class. Other files are Java equivalents of COM interfaces that are exposed by the server. These interfaces, such as Adder_dispatchdefault.java, belong to the "removal" (Dispatch) interface, which is part of the communication mechanism between the automation controller and the Automation server. Java/com integration features also support the implementation and use of dual interfaces. However, the IDispatch and dual interface issues are beyond the scope of this appendix.
Below, you can see the corresponding customer code. The first line only imports packages generated by JActiveX. It then creates and uses an instance of the COM Automation server, as if it were an original Java class. Note the type model in the row, where "example" is a COM object (that is, an instance of the build and call it). This is consistent with the COM object model. In COM, programmers never get a reference to an entire object. Instead, they can only have references to one or more interfaces implemented within a class.
An example of a Java object in the Adder class is the equivalent of instructing the COM activation server and creating an instance of the COM object. But then we have to specify which interface we want to use and pick one in the interface implemented by the server. This is exactly the kind of work that type models do. Here is the "default removal" interface, which is the standard interface used by the automation controller to communicate with the same Automation server. For details on this, please refer to the "Inside COM" edited by ibid. Please note how easy it is to activate the server and select a COM interface!
Import javaadder.*;
public class Javaclient {public
static void Main (String [] args) {
Adder_dispatchdefault Iadder =
(Adder_dis Patchdefault) New Adder ();
Iadder.setaddend (3);
Iadder.sum ();
Iadder.sum ();
Iadder.sum ();
System.out.println (Iadder.getresult ());
}
Now we can compile it and start running the program.
1. com.ms.com Package
The com.ms.com package defines a large number of classes for COM development. It supports the use of--variant (variants) and SAFEARRAY automation (safe array Automation) types for GUIDs--to deal with ActiveX controls at a deeper level and to control COM exceptions.
Due to its limited space, it is not possible to cover all these themes. But I want to highlight the problem of COM anomalies. According to the specification, almost all COM functions return an HRESULT value that tells us whether the function call was successful and why it failed. However, if you observe the Java method signatures in the server and client code, you will find no HRESULT. Instead, we retrieve the data from some functions using the function return value. The virtual machine (VM) converts Java-style function calls into COM-style function calls, even including return parameters. But what if one of the functions we call in the server fails at the COM level and what happens in the virtual machine? In this case, the JVM considers the HRESULT value to mark a failure, and produces an intrinsic Java exception to the class Com.ms.com.ComFailException. In this way, we can use the Java Exception Control mechanism to manage COM errors instead of checking the return value of the function.
For more information on the classes included in this package, refer to Microsoft's product documentation.