OHSWG 1997.12.15
OHSWG logo

Open Hypermedia Systems Working Group

DCOM


DCOM Example

This simple example is taken from Client/Server Programming with Java and CORBA by Robert Orfali and Dan Harkey. It is the same example used for the CORBA evaluation, in this the software used is MS Visual Java running on Windows NT. It allows not only the programming style to be compared but also the performance of the two approaches. The server object maintains a counter which can be incremented by its clients. Round-trip network performance (e.g. a ping) for the component technology can be roughly measured by computing the elapsed time divided by n, where n is a large number of individual increment calls. (In the book, Java-based CORBA technologies averaged 3.4 milliseconds using a JIT compiler, 6.3 msecs without. While the DCOM Java version was slightly slower, averaging 3.9 msecs over 10Mbit/s Ethernet).

As with CORBA the first step in using DCOM is defining a component's interface. This is accomplished by writing an IDL file. Remember that this is DCOM IDL, not CORBA. The IDL for the counter server is shown below (example code on this page is Copyright © Robert Orfali and Dan Harkey, 1997):



// Count.idl

[
	uuid(66892570-5F62-11d1-99E3-0060084A1358),
	version(1.0)
]

library Counter
{
	[
		object,
		uuid(66892571-5F62-11d1-99E3-0060084A1358),
		pointer_default(unique),
		oleautomation
	]
	interface ICount : IUnknown
	{
		import "oaidl.idl";

		HRESULT set_sum([in] int val);
		HRESULT get_sum([out, retval] int* retval);
		HRESULT increment([out, retval] int* retval);
	};

	importlib("stdole32.tlb");
	[
		uuid(66892572-5F62-11d1-99E3-0060084A1358),
	]
	coclass Count
	{
		[default] interface ICount;
	};
};


This defines an ICount interface with three functions declared for getting, setting and incrementing the value. The long number strings are GUIDS, generated by the Micosoft Developer Studio's Create GUID menu option. This is a 128-bit number based on time and network address that is assumed to be universally unique.

The next step is to compile this file using an DCOM IDL compiler. The one provided with DevStudio is MIDL. It produces a type library file which defines the new component. The type library must be registered with the system. The javatlb tool then uses the type library to produce a class summary file as well as the ICount and Count class files themselves.

Although the base class files have been produced for you by javatlb, they only implement the ICount DCOM server, a default factory implementation that can create instances of the IClass component. The actual implementation of the IClass methods must be provided by hand in a java file. In this case Count.java (shown below).



// Count.java: The Count implementation

//N.B. Both the class constructor and the main method 
//are taken care of by DCOM. The com.ms.com import is
//for exceptions (each method must throw a ComException)

import com.ms.com.*
import count.*;

class Count implements ICount
{
	private int sum;

	public int get_sum() throws ComException
	{
		return sum;
	}

	public void set_sum(int val) throws ComException
	{
		sum = val;
	}

	public int increment() throws ComException
	{
		sum++;
		return sum;
	}
}

Lastly the Count component must be compiled and placed in the java\trustlib directory (of WinNT). Once there it can be registered for use with javareg.

The client application has not been forgotten. The following code obtains a reference to the ICount interface and increments it 1000 times. Printing out statistical information as it goes. Note that the import count.* allows the interface to be manipulated very easily via Java, similarly to any normal class object.



//CountDCOMClient.java

import count.*

class CountDCOMClient
{
	public static void main(String args[])
	{
		try
		{
			//Bind to Count object
			System.out.println("Creating Count Object");
			ICount counter = (ICount)new count.Count();

			//Set sum to initial 0
			System.out.println("Setting sum to 0");
			counter.set_sum((int)0);

			//Calculate start time
			long startTime = System.currentTimeMillis();

			//Increment 1000 times
			System.out.println("Incrementing");
			for(int i = 0; i < 1000; i++)
			{
				counter.increment();
			}

			//Calculate stop time and print stats
			lonf stopTime = System.currentTimeMillas();
			System.out.println("Avg Ping = "
					+ ((stopTime - startTime)/1000f)
					+ " msecs");
			System.out.println("Sum = " + counter.get_sum());
		}
		catch (Exception e)
		{
			System.err.println("System Exception");
			System.err.println(e);
		}

	} //end main

} //end CountDCOMClient class

The client program must also now be compiled to the trustlib directory.

To run the client on the servers machine we simply run CountDCOMClient via jview, this runs the count object as an Inprocess Server, this seems to be the default when obtaining references via Java. To run the client on a remote machine requires some configuration on that machine. We must configure DCOM via DCOMCNFG, firstly enabling it and also indicating that the DCOM object will run on a remote machine. Unfortunately this is not all that is needed. The registry must also be altered. DCOM will not call a remote machine as long as InprocServer32 or LocalServer32 entries are found in the registry (under HKEY_CLASSES_ROOT and the appropriate GUID). Microsoft is well aware that this is a messy way of doing things and is working on a solution.

Once all this is done though, the client may be run via jview as normal and will call the remote DCOM server. Voila!


Start Page Description Example Availability Recommendations References


David Millard
U Southampton, England
dem97r@ecs.soton.ac.uk
---