|
Introducing COM+In addition to plain COM servers, Delphi also allows you to create enhanced COM objects, including stateless objects and transaction support. Microsoft first introduced this type of COM object with the MTS (Microsoft Transaction Server) acronym in Windows NT and 98, and later renamed it COM+ in Windows 2000/XP (I'll call it COM+, but I'm referring to both MTS and COM+). Delphi supports building both standard stateless objects and DataSnap remote data modules based on stateless objects. In both cases, you begin development by using one of the available Delphi wizards, using the New Items dialog box and selecting the Transactional Object icon on the ActiveX page or the Transactional Data Module icon on the Multitier page. You must add these objects to an ActiveX library project, not to a plain application. Another icon, COM+ Event Object, is used to support COM+ provides a run-time environment supporting database transaction services, security, resource pooling, and an overall improvement in robustness for DCOM applications. The run-time environment manages objects called COM+ components. These are COM objects stored in an in-process server (that is, a DLL). Whereas other COM objects run directly in the client application, COM+ objects are handled by this run-time environment, in which you install the COM+ libraries. COM+ objects must support specific COM interfaces, starting with IObjectControl, which is the base interface (like IUnknown for a COM object). Before getting into too many technical and low-level details, let's consider COM+ from a different perspective: the benefits of this approach. COM+ provides a few interesting features, including:
Creating a COM+ ComponentThe starting point for creating a COM+ component is the creation of an ActiveX library project. Then, follow these steps:
Once you've compiled an ActiveX library, or COM library, which hosts a COM+ component, you can use the Component Services administrative tool (shown in the Microsoft Management Console, or MMC) to install and configure the COM+ component. Even better, you can use the Delphi IDE to install the COM+ component using the Run ® Install COM+ Object menu command. In the subsequent dialog box, you can select the component to install (a library can host multiple components) and choose the COM+ application where you want to install the component: A COM+ application is nothing more than a way to group COM+ components; it is not a program or anything like one (why they call it an application is not clear to me). So, in the Install COM+ Object dialog, you can select an existing application/group, choose the Install Into New Application page, and enter a name and description. I've called the COM+ application Mastering Delphi Com+ Test, as you can see in Figure 12.12 in Microsoft's Component Services administration console. This is the front end you can use to fine-tune the behavior of your COM+ components, setting their activation model (just-in-time activation, object pooling, and so on), their transaction support, and the security and concurrency models you want to use. You can also use this console to monitor the objects and method calls (in case they take a long time to execute). In Figure 12.12, you can see that there are currently two active objects. Figure 12.12: The newly installed COM+ component in a custom COM+ application (as shown by Microsoft's Com-ponent Services tool)
I've created a client program for the COM+ object, but it is like any other Delphi COM client. After importing the type library, which is automatically registered while installing the component, I created an interface-type variable referring to it and called its methods as usual. Transactional Data ModulesThe same types of features are available when you create a transactional data module—a remote data module within a COM+ component. Once you've created a transactional data module, you can build a Delphi DataSnap application (as you'll see in Chapter 16, "Multitier DataSnap Applications"). You can add one or more dataset components, add one or more providers, and export the provider(s). You can also add custom methods to the data module type library by editing the type library or using the Add To Interface command. Within a COM+ component or transactional data module, you can also use specific methods that support transactions. These methods are technically provided, at a lower level, in the IObjectContext interface returned by the GetObjectContext method:
Other methods of the IContextObject interface include CreateInstance, which creates another COM+ object in the same context and within the current transaction; IsCallerInRole, which checks if the object's caller is in a particular "security" role; and IsSecurityEnabled (whose name is self-explanatory). Once you've built a transactional data module within a server library, you can install it as I showed earlier for a plain COM+ object. After the transactional data module has been installed, it will be directly available to other applications and visible in the management console. An important feature of COM+ is that it becomes much easier to configure DCOM support using this environment. A client computer's COM+ environment can grab information from a server computer's COM+ environment, including registration information for the COM+ object you want to be able to call over a network. The same network configuration is much more complex if done with plain DCOM, without MTS or COM+.
COM+ EventsClient applications that use traditional COM objects and Automation servers can call methods of those servers, but this is not an efficient way to check whether the server has updated data for the client. For this reason, a client can define a COM object that implements a callback interface, pass this object to the server, and let the server call it. Traditional COM events (which use the IConnectionPoint interface) are simplified by Delphi for Automation objects, but are still complex to handle. COM+ introduces a simplified event model, in which the events are COM+ components and the COM+ environment manages the connections. In traditional COM callbacks, the server object has to keep track of the multiple clients it has to notify, something Delphi doesn't provide us automatically (the default Delphi event code is limited to a single client). To support COM callbacks for multiple clients you need to add the code to hold references to each of the clients. In COM+, the server calls into a single event interface, and the COM+ environment forwards the event to all clients that have expressed interest in it. This way, the client and the server are less coupled, making it possible for a client to receive notification from different servers without any change in its code.
To create a COM+ event, you should create a COM library (or ActiveX library) and use the COM+ Event Object wizard. The resulting project will contain a type library with the definition of the interface used to fire the events, plus some fake implementation code. The server that receives the notification of the events will provide the interface implementation. The fake code is there only to support Delphi's COM registration system. While building the MdComEvents library, I added to the type library a single method with two parameters, resulting in the following code (in the interface definition file): type IMdInform = interface(IDispatch) ['{202D2CC8-8E6C-4E96-9C14-1FAAE3920ECC}'] procedure Informs(Code: Integer; const Message: WideString); safecall; end; The main unit includes the fake COM object (notice that the method is abstract, so it has no implementation) and its class factory, to let the server register itself. At this point, you can compile the library and install it in the COM+ environment, following these steps:
To test whether it works, you'll have to build an implementation of this event interface and a client invoking it. The implementation can be added to another ActiveX library, hosting a plain COM object. Within Delphi's COM Object Wizard, you can select the interface to implement from the list that appears when you click the List button. The resulting library, which in my example is called EvtSubscriber, exposes an Automation object: a COM object implementing the IDispatch interface (which is mandatory for COM+ events). The object has the following definition and code: type TInformSubscriber = class(TAutoObject, IMdInform) protected procedure Informs(Code: Integer; const Message: WideString); safecall; end; procedure TInformSubscriber.Informs(Code: Integer; const Message: WideString); begin ShowMessage ('Message <' + IntToStr (Code) + '>: ' + Message); end; After compiling this library, you can first install it into the COM+ environment, and then bind it to the event. This second step is accomplished in the Component Services management console by selecting the Subscriptions folder under the event object registration, and using the New ® Subscription shortcut menu. In the resulting wizard, choose the interface to implement (there is probably only one interface in your COM+ event library); you'll see a list of COM+ components that implement this interface. Selecting one or more of them sets up the subscription binding, which is listed under the Subscriptions folder. You can see an example of my configuration while building this example in Figure 12.13. Finally, you can focus on the application that fires the event, which I've called Publisher (because it publishes the information other COM objects are interested in). This is the simplest step of the process, because it is a plain COM client that uses the event server. After importing the COM+ event type library, you can add to the publisher code like this: var Inform: IMdInform; begin Inform := CoMdInform.Create; Inform.Informs (20, Edit1.Text); My example creates the COM object in the FormCreate method to keep the reference around, but the effect is the same. Now the client program thinks it is calling the COM+ event object, but this object (provided by the COM+ environment) calls the method for each of the active subscribers. In this case you'll end up seeing a message box: To make things more interesting, you can subscribe the same server twice to the event interface. The net effect is that without touching your client code, you'll get two message boxes, one for each of the subscribed servers. Obviously this effect becomes interesting when you have multiple different COM components that can handle the event, because you can easily enable and disable them in the management console, changing the COM+ environment without modifying any program code. |
|
Copyright © 2004-2024 "Delphi Sources" by BrokenByte Software. Delphi Programming Guide |
|