Xml Automation Bridge

 

We introduce XML programming at no cost.

Usually ActiveX components or COM servers are used by code like this (here in Visual Basic) :

 	Set t = CreateObject("COMServer.MyObject")
	MsgBox t.Description
Now what if it becomes possible to use XML to do the same ? In other words,
<?xml version="1.0">
<XmlAutomationBridge>
  <server registry="COMServer.MyObject">
    <IMyObject Description="">
    </IMyObject>
  </server>
</XmlAutomationBridge>
Before we get into advantages of XML programming over usual VB or automation programming, let us start with a small architecture model :

 

Sample Image

 

 

An introduction to an XML programming language

Instead of using Visual Basic or other automation language, XML provides a more cross-platform client framework that allows to execute methods on a COM server, whether the COM server is executed on the same machine, or remote , or even behind a web server.

The beauty of that Xml Automation Bridge is that it allows true XML programming without adding or even updating a single line of code to your SDK : my only assumption is that target COM servers expose dispatch interfaces (usually available to VB or other automation languages).

This Xml Automation Bridge can be regarded as a proxy. Because this proxy lives on the client-side, it does not require any change on already deployed servers.

This framework provides a unique programming model through the XML language metaphore. In next section is described the few rules of the model.

Of course, there is a lot of things in common with what is known as "Web services". Beyond the fact that web services is still at the marketing stage, and requires a lot of redeployment (SOAP, web server, proxies, WSDL modeling, ...), especially on the server-side, the Xml Automation Bridge fits much better the goal of web services in that it does not need any server-side deployment and exactly matches the SDK object model exposed by any combination of COM servers. In other words, the Xml Automation Bridge is ready-to-use and a simple "upgrade" for people who are used to Visual Basic and the like. That's a great opportunity to switch to XML programming.

 

Entering COM interfaces, asking where we are , going one way executing methods, crossing two ways, and so on

  • of course the real thing begins by attaching your XML code to a COM server. This goes like this :
  <server registry="clsid or progid">
    ...
  </server>
 

The clsid is a global COM identifier of the form {5D0CE852-D909-11CF-91FC-00A0C903976F}, while the progid is something of the form COMObject.MyObject, such like Excel.Application. VB Users usually rely on progids to create instances of servers. Use either.

Using XML, the begin tag creates an instance of the server, while the end tag automatically shuts down this instance of the server, allowing to accurately control the life cycle of the servers. In other words, the XML run-time starts parsing and executing XML code, and as a consequence reaches the server tag. The server instance is created. Then all XML code within the begin and end tags is executed in this context. Finally the XML run-time reaches the server end-tag, which is the end of scope of the running server instance.

 

  • executing methods and traversing the object model

Once a server is running, the XML run-time allows to execute any method or retrieve property values at any interface level, provided the interface is Automation-friendly in the IDL interface description (server-side), in other words interfaces deriving from IDispatch or dispinterface.

Of course, any combination of method execution is possible at this point. Scope and hierarchy allow both to work with interfaces, execute methods, and traverse interfaces. Below is a sample where we assume the COM server allows a client to open documents :

   <server registry="clsid or progid">
     <IApplication property="Documents">
       <IDocuments Open="mydoc.xls">
         <IDocument Process=""/>
         <IDocument SaveAs="mydoc.pdf"/>
       </IDocuments>
     </IApplication>
   </server>
 

It is possible to pass more than one parameter using commas, for instance Process="1, 10, arstdesign@hotmail.com". A special case is no parameter at all : pass the method name as attribute and associate an empty attribute value to it, such like in the sample above.

Parameters are passed to the COM servers using the built-in type library data type binding automatically provided by COM automation interfaces. That's an advantage and the programmer needs no additional code to support it.

Properties exposed by interfaces are also retrieved with the special property attribute.

Now that we know how to execute a method, we have however assumed that we knew the name of the method and the parameters to pass along. So let's continue :

 

  • discovering exposed methods and parameters

One must admit, and I am first to do this, that several tools already can help end-developers to know every tiny details about methods exposed by a given interface. One of these tools is OLE Viewer, from the VisualStudio devtool.

Here is what's displayed when using OLE Viewer in our COMServer.MyObject sample :

We need an adequate XML tool to do this, so let XML Automation Bridge be that one. From the sample IDL interface excerpt below :

	//  Primary dispatch interface for CObjectTwo
	[ 
		uuid(AD0CE852-D909-11CF-91FC-00A0C903976F), 
		helpstring("IObjectOne Interface")
	]
	interface IObjectOne : IDispatch
	{
		[propget, id(1)] HRESULT OneSayHello([out,retval] BSTR* bstr);
	};


	[ 
		uuid(5D0CE851-D909-11CF-91FC-00A0C903976F), 
		dual,
		helpstring("IMyObject Interface")
	]
	interface IMyObject : IDispatch
	{
		[propget, id(1)] HRESULT Description([out,retval] BSTR* bstr);
		[id(2)] HRESULT Process([in]long n, [out,retval] IObjectOne **p);
	};

	//  Class information for CMyObject

	[ uuid(5D0CE852-D909-11CF-91FC-00A0C903976F) ]
	coclass MyObject
	{
		[default] interface IMyObject;
	};

Here is what we get when we put the following XML code :

  <?xml version="1.0" encoding="UTF-8"?>
  <server registry="comserver.MyObject">
    <IMyObject method="*" output="c:\temp.xml">
    </IMyObject>
  </server>

We get the following XML result in c:\temp.xml :

<?xml version="1.0" encoding="UTF-8"?>
<XmlAutomationBridge>
 <IMyObject>
  <Description params="" return="BSTR* bstr"/>
  <Process params="[in]long n" return="IObjectOne** p"/>
 </IMyObject>
</XmlAutomationBridge>

which is as everyone can see the exact equivalent of what is shown by OLE Viewer.

Please note the * discovery activator in the input XML and the output attribute indicating the XML result file where the XML run-time is going to store the discovery result. In the resulting discovery XML, the interface IMyObject has child elements which are executable method names, with input params attributes (with full data typing), and return value detailed in the return attribute.

 

How to use this proxy

Syntax from the command line :

  demo.exe <input xml file>

To execute the sample provided in this article, you need to do the following :

  1. copy demo.exe, COMServer.exe and demo.xml somewhere
  2. register the COM Server with the command line : COMServer /regserver
  3. then test the XML execution with the command line : demo demo.xml

 

What about web services ?

All this looks a lot like what is known behind web services. That's true, except that the XML Automation Bridge is a much more adequate proxy component to use because it is linked on the client-side (it's a .lib library), not on the server-side : developers interested in web services should give a glance at architecture charts in web service specifications and vendor implementations : this is horrible ! Many components, dependance with web servers, ...

On the contrary, the XML Automation Bridge can be linked on the client-side to manage all COM dispatching and life cycle against one or more COM servers. Thus no deployment cost.

 

Technical details

- demo.dsp (demo.exe), a straight forward sample that uses the XmlAutomationBridge library.

- XmlAutomationBridge.dsp (XmlAutomationBridge.lib), the application logic that executes arbitrary XML code provided in a .xml file, against any COM server. It has the following class implementation :

  • HostSite.cpp : manages XML reading, and all interfaces life cycle.
  • Context.cpp : several basic contexts for executing methods exposed by COM interfaces.
  • XmlWriter.cpp : a simple XML writer (discovery mode).
  • XmlFileManager.cpp : manages XML stream reading, including async monikers for URL-based XML streams.

- xmlparser.dsp (xmlparser.lib), an XML reader (by James Clark).

- COMServer.dsp (COMServer.exe), a COM server (must be registered before use) exposing a sample interface to play with.

 

What's next ?

XML hierarchies allow a great way to manage COM servers life cycles by using serialization and parallelisation, thanks to synchronisation points. It would be more than useful to introduce a thread manager and allow master interfaces to synchronize, wait, rerun, or even kill slave interfaces. Thanks to this, many real-world intuitive business logic applications could see the light of day.

 

 

Stephane Rodriguez-
July 28, 2002.


Home
Blog