COM+ Technical Series: Loosely Coupled Events

Scenario #2 of 3

Microsoft Corporation

September 1999

Summary: Provides a description of COM+ Events. (7 printed pages)

Loosely Coupled Events—Application Scenario

Notifying interested parties that there have been changes to information is a fundamental issue of distributed computing. In the past, subscribers were provided with an interface on which a method call could periodically be called to determine if changes had taken place. Such a procedure is known as polling the publisher. While polling is a simple way to obtain the required information, there are some disadvantages to using this method. Polling wastes time for both the publisher and subscriber. The subscriber must send a method call to the publisher and the publisher must relay an answer to the subscriber—even if there have been no changes in the information. Polling also involves a time lag between when the information actually changed and when the subscriber polls for it.

Ideally, an events system should provide a way to initiate the notification of interested parties when information changes. In a tightly coupled event (TCE), the publisher is provided with an interface on which to call a method when a change occurs. COM Connection Points are an example of a TCE system. The subscriber in a TCE system knows which publisher to request notification from and the interfaces that are exposed. A TCE system requires both the publisher and subscriber to be running at all times. Additionally, the mechanism used to connect the callback interface must be known in advance, and these mechanisms can be widely divergent. TCEs also provide no way to filter or intercept an event. (Filtering is a way to designate event notification only when certain changes occur or when certain values are reached. For example, you may want to know about your favorite stock only when it reaches a predetermined price.)

COM+ Events is a loosely coupled events (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. Subscribers query this store and select the events that they want information about. Selecting event information from the event store creates a subscription. When an event occurs, the event system checks this database to find the interested subscribers, creates a new object of each interested class, and calls a method on that object.

Loosely Coupled Events Code Samples

Using Loosely Coupled Events and Visual Basic 6.0

The steps for implementing COM+ Events in Visual Basic® 6.0 are short and simple.

  1. Create an event class DLL.

    This is a standard Visual Basic ActiveX® DLL with the following attributes:

    There should be no other code in this module.

    Example:

    DLL Name is My_Events, Class Name is Account
    
    Public Sub LoginSuccessful(ByVal Email As String, _ ByVal FullName As String, 
    ByVal AccountID As Long)
    End Sub
    
  2. Create a subscriber DLL.

    This is also a standard Visual Basic ActiveX DLL with the following attributes:

    Create Private Sub() methods that correspond to each of the Public Sub() methods in the event class DLL, preceding the name of the Sub() with the name of the interface and an underscore.

    Example:

     
    Implements My_Events.Account
    
    Private Sub Account_LoginSuccessful(ByVal Email As String, _ ByVal FullName As 
    String, ByVal AccountID As Long)
    ‘Code to do something based on event goes here
    End Sub
    
  3. Install your DLLs with the COM+ Explorer:
    1. Create a new application.

    2. Install the event class DLL as an EventClass component.

    3. Install the subscriber DLL as a regular component.

    4. Under the Subscriptions folder of the subscriber DLL, create a New Subscription and point it at your event class.

    Wizards in the COM+ Explorer will walk you through each of the above steps.

  4. Publish the event.

    To publish an event, simply call CreateObject() on the event class DLL you previously created and then call the appropriate method to publish the event.

    Example:

    Dim objEventClass As Object
    Set objEventClass = CreateObject(“My_Events.Account”)
    objEventClass.LoginSuccessful(“KingDaddy@Hotmail.com, “, _”Elvis is the King”,100000)
    Set objEventClass = Nothing
    

Using COM+ Events in Visual C++ 6.0

The steps for implementing COM+ Events in Visual C++® 6.0 are short and simple.

  1. Create an event class DLL.

    This simple COM object defines the event interface and event handler method prototypes (there should be no implementation in this object).

    Example:

    // EventClass.idl    
    //////////////////////////////////////////////////////
    // ISystemEvents Interface
    [
        uuid(6DBAC91E-D1E2-11d2-9A34-00C04F72EB9B),
        helpstring(“ISystemEvents Interface”),
        oleautomation,
        pointer_default(unique)
    ]
    interface ISystemEvents : IUnknown
    {
        [helpstring(“method ProcessCreated”)] HRESULT 
    ProcessCreated(BSTR szProcessName);
        [helpstring(“method ProcessTerminated”)] HRESULT 
    ProcessTerminated(BSTR szProcessName);
    }
    
    // Event Sub(scriber) Class
    [
        uuid(992FE540-D1E3-11D2-9A34-00C04F72EB9B),
        helpstring(“EventSubClass Class”)
    ]
    coclass EventSubClass
    {
        interface ISystemEvents;
    };
    
    
    
    
    
    // EventClass.h : Declaration of the CEventClass Class
    /////////////////////////////////////////////////////////////////
    // CEventClass
    
    class ATL_NO_VTABLE CEventClass : 
        public CComObjectRootEx,
        public CComCoClass
    {
    public:
        CEventClass()
        {
        }
    
    public:
    };
    
  2. Create a subscriber DLL.

    This is also a standard Visual C++ COM object with the following attributes:

    Example:

    // EventSubImpl.h : Declaration of the CEventSubImpl
    //////////////////////////////////////////////////////////////////////
    // CEventSubImpl
    class ATL_NO_VTABLE CEventSubImpl : 
        public CComObjectRootEx,
        public CComCoClass,
        public IDispatchImpl<&LIBID_EventSUBSCRIBERLib>,
        public ISystemEvents
    {
    public:
        CEventSubImpl()
        {
        }
    
    BEGIN_COM_MAP(CEventSubImpl)  
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(ISystemEvents)
    END_COM_MAP()
    
    public:
        // ISystemEvents methods
        STDMETHOD (ProcessCreated)(BSTR);
        STDMETHOD (ProcessTerminated)(BSTR);
    };
    
    
    
    
    
    // Subscriber implements methods to handle the captured
    //     ISystemEvents events. 
    // EventSubImpl.cpp : Impl of CEventSubImpl
    /////////////////////////////////////////////////////////////
    // CEventSubImpl
    
    STDMETHODIMP CEventSubImpl::ProcessCreated(BSTR bstr)
    {
        return CommonMethod(_T(“ProcessCreated”),bstr);
    }
    
    STDMETHODIMP CEventSubImpl::ProcessTerminated(BSTR bstr)
    {
        return CommonMethod(_T(“ProcessTerminated”),bstr);
    }
    
  3. Install your DLLs with the COM+ Explorer:
    1. Create a new application.

    2. Install the event class DLL as an EventClass component.

    3. Install the subscriber DLL as a regular component.

    4. Under the Subscriptions folder of the subscriber DLL, create a New Subscription and point it at your event class.

    Wizards in the COM+ Explorer will walk you through each of the above steps.

  4. Publishing the event.

    To publish an event, create the event class object (also accomplished using ISystemEvents) and then call the appropriate event handler method (ProcessCreated or ProcessTerminated—implemented by the subscriber) to fire the event.

    Example:

    LRESULT CFoo::FireSystemMethod(IUnknown* punk, BSTR bstrval, 
    int i)
    {
        ISystemEvents    *psystem =0;
    
        HRESULT hr = punk->
    QueryInterface(__uuidof(ISystemEvents), (void**)&psystem);
        exit(hr);
    
        switch(i)
        {
        case 0:    // ProcessCreated
            // Event firing happens here
            hr = psystem->ProcessCreated(bstrval);
            break;
    
        case 1: // ProcessTerminated
            // Event firing happens here
            hr = psystem->ProcessTerminated(bstrval);
            break;
    exit:
        RELEASE(psystem);
        return hr;
    }

Using Loosely Coupled Events

COM+ Events matches and connects publishers and subscribers. An event is a single method in a COM+ interface, originated by a publisher and dispatched to the correct subscriber or subscribers. A publisher makes the method call to initiate an event and a subscriber receives these calls from the publisher. COM+ Events maintains the list of interested subscribers who will receive the calls and directs those calls without requiring the knowledge of the publisher.

The connection between publisher and subscriber(s) is known as an EventClass. An EventClass is a COM+ component that declares the interface used by a publisher to fire events. The subscriber must implement these interfaces in order to receive events. To do so, specify the interfaces and methods you want an EventClass to contain by providing a type library (using Visual Basic), or by inheriting from the appropriate interfaces (such as Visual C++). EventClasses are stored in the COM+ event store (COM+ catalog), by publishers using either the COM+ Administrative SDK functions or the Component Services administration tool.

To register an event in the event system, a publisher creates one or more EventClasses. This EventClass indicates the events that can occur and, optionally, identifies the publisher. Then the publisher instantiates the EventClass by calling CoCreateInstance or CreateObject and requesting the event interface be returned. The instantiated EventClass object contains the event system’s implementation of the requested interface. By invoking the appropriate method through the event interface, the publisher automatically fires an event on the EventClass object. COM+ Events searches the subscription database (COM+ catalog) to find all the subscribers who have registered subscriptions to that interface and method. It connects to those subscribers (by direct creation, monikers, or queued components) and calls the method. To support more than one subscriber notification for an event, methods can contain only input parameters and must return only success or failure HRESULTs.

The following diagram depicts the COM+ Events architecture.

Figure 1. COM+ Events architecture