Paul Gielens recently posted an entry on his weblog to ask for advise on how to remote events to subscribers of said events. Choosing from three alternatives (MSMQ, DCOM and Loosely Coupled Events (LCE)) I suggested that LCE might be an interesting choice. Paul then contacted me on some details on how to implement LCE where the events have to be remoted to different machines. I thought I might as well share the details.
Loosely Coupled Events two minute abstract
LCE uses an event class that implements an well-known interface that forms the contract between the publisher of events and its subscribers. The event class doesn’t actually have any real implementation. All calls made by publisher will be intercepted by COM+ (as always for configured components) and redirected to all subscribers. Two types of subscribers exist: persistent and transient. The persistent subscribers are configured classes in a COM+ server application that have a subscription that is administered through the Component Services MMC snap-in. A single object from this class is activated if the event is fired. Transient subscription are made programmatically, are short-lived in general and register an existing object as the subscriber. No activation of objects needed. Typically the transient subscriptions will be made by applications.
In this entry I will focus on persistent subscribers in a COM+ server application.
The default way to create a remote component in COM+ (aka Enterprise Services) is exporting an application as an Application Proxy, that you will install on the remote machine. When you instantiate an object from any of the configured classes in that application, you will actually activate in on the server from which the application was exported (expert note: unless you set the RSN (Remote Server Name) on the Activation tab of the application before exporting it. Then the object will be activated on the server specified in the RSN). The picture below shows three COM+ application types, where COMPlusProgramming is an Application Proxy. It has a new icon in COM+ 1.5, so it is easily recognizable.
This way you could export the event class, the persistent subscriber classes or both to remote machines. Let’s think about that for a second. For a event class, once exported, the server that has the application proxy installed will be the publishing server. It will call the event on the event class, which will be activated on the remote server, being the one from which the proxy was exported (I’ll call this one the original server). Sounds like the world upside down, doesn’t it. Also, in this manner, you will not be able to create multiple subscribers on different machines. The original server can have one or more subscriptions to the event, but these subscribers are all local. Alternatively, you could try to add a subscription to the exported subscriber classes. Except…, you cannot do so in an application proxy.
There’s is actually a better way to create a remote subscription. The key is in the record of the sunscriptions that are stored inside the COM+ catalog. They hold the PublisherCLSID and an optional server name. Setting this server name to the remote subscribing server, will activate the subscriber class when the event is fired, but on the remote machine instead of locally. It will use DCOM to do so. No programming involved on that part. You will create regular subscriptions on the publishing server for all remote machines that need to have one. You then set the Server Name on the Options tab of the subscription Properties dialog. Mind you, you can create more than one subscription on the same subscriber class for the same interface, if you want to send the event to multiple servers. Each of the subscription needs to have a different Server name corresponding to one of the servers, obviously.
In this picture you can see how two subscriptions have been made to the same IStockOption interface implements by DistributedLCE.StockOptionEventClass. For each of these subscriptions, the remote Server name has been set, to KILLER-DEVELOP1 and KILLER-DEVELOP2 respectively (two server machines). You can see the place where to set this in the dialog below.
In the picture you can also see that there is a checkbox to make the event calls using Queued Components (QC). If you look at it that way (Paul, pay attention here, please), if you use LCE, you can have both loosely coupled events, MSMQ (underlying infrastructure for QC) and DCOM (used for remoting calls to remote subscriber machines). So why make a choice? You can have it all!
For your experimenting pleasure, find enclosed the zip file with the code for the DistributedLCE solution, so you can try this for yourself. Run regsvcs.exe on DistributedLCE.dll and place it in the Global Assembly Cache as well. Then add subscriptions to the DistributedLCE.StockOptionSubscriberClass. Run the Windows application to fire events and see the magic happen.
If you have any questions or suggestions, drop me a comment. I’d love to hear your experiences on this.