Delphi Programming Guide
Delphi Programmer 

Menu  Table of contents
Bookmark and Share

Part I - Foundations
  Chapter 1 Delphi 7 and Its IDE
  Chapter 2 The Delphi Programming Language
  Chapter 3 The Run-Time Library
  Chapter 4 Core Library classes
  Chapter 5 Visual Controls
  Chapter 6 Building the User Interface
  Chapter 7 Working with Forms
Part II - Delphi Object-Oriented Architectures
  Chapter 8 The Architecture of Delphi Applications
  Chapter 9 Writing Delphi Components
  Chapter 10 Libraries and Packages
  Chapter 11 Modeling and OOP Programming (with ModelMaker)
  Chapter 12 From COM to COM+
Part III - Delphi Database-Oriented Architectures
  Chapter 13 Delphi's Database Architecture
  Chapter 14 Client/Server with dbExpress
  Chapter 15 Working with ADO
  Chapter 16 Multitier DataSnap Applications
  Chapter 17 Writing Database Components
  Chapter 18 Reporting with Rave
Part IV - Delphi, the Internet, and a .NET Preview
  Chapter 19 Internet Programming: Sockets and Indy
  Chapter 20 Web Programming with WebBroker and WebSnap
  Chapter 21 Web Programming with IntraWeb
  Chapter 22 Using XML Technologies
  Chapter 23 Web Services and SOAP
  Chapter 24 The Microsoft .NET Architecture from the Delphi Perspective
  Chapter 25 Delphi for .NET Preview: The Language and the RTL
  Appendix A Extra Delphi Tools by the Author
  Appendix B Extra Delphi Tools from Other Sources
  Appendix C Free Companion Books on Delphi
  List of Figures    
  List of tables    
  List of Listings    
  List of Sidebars  

Previous Section Next Section

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+ events.

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:

Role-Based Security  The role assigned to a client determines whether it has the right to access the interface of a data module.

Reduced Database Resources  You can reduce the number of database connections, because the middle tier logs on to the server and uses the same connections for multiple clients (although you cannot have more clients connected at once than you have licenses for the server).

Database Transactions  COM+ transaction support includes operations on multiple databases, although few SQL servers other than Microsoft's support COM+ transactions.

Creating a COM+ Component

The starting point for creating a COM+ component is the creation of an ActiveX library project. Then, follow these steps:

  1. Select a new Transactional Object in the ActiveX page of the New Items dialog box.

  2. In the resulting dialog box (see Figure 12.11), enter the name of the new component (ComPlus1Object in my ComPlus1 example).

    Click To expand
    Figure 12.11: The New Trans-actional Object dialog box, used to create a COM+ object

    The New Transactional Object dialog box allows you to enter a name for the class of the COM+ object, the threading model (because COM+ serializes all the requests, Single or Apartment will generally do), and a transactional model:

    Requires a Transaction  Indicates that each call from the client to the server is considered a transaction (unless the caller supplies an existing transaction context).

    Requires a New Transaction  Indicates that each call is considered a new transaction.

    Supports Transactions  Indicates that the client must explicitly provide a transaction context.

    Does Not Support Transaction  (The default choice, and the one I've used.) Indicates that the remote data module won't be involved in any transaction. This option prevents the object from being activated if the client calling it has a transaction.

    Ignores Transactions  Indicates that objects do not participate in transactions, but can be used regardless of whether the client has a transaction.

  3. As you close this dialog, Delphi adds a type library and an implementation unit to the project and opens the type-library editor, where you can define the interface of your new COM object. For this example, add a Value integer property, an Increase method having as its parameter an amount, and an AsText method returning a WideString with the formatted value.

  4. As you accept the edits in the type-library editor (by clicking the Refresh button or closing the window), Delphi shows the Implementation File Update Wizard, but only if you set the Display updates before refreshing option of the Type Library page of the Environment Options dialog box. This wizard asks for your confirmation before adding four methods to the class, including the get and set methods of the property. You can now write some code for the COM object, which in my example is quite trivial.

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:

Click To expand

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.

Click To expand
Figure 12.12: The newly installed COM+ component in a custom COM+ application (as shown by Microsoft's Com-ponent Services tool)

Because you've created one or more objects, the COM library remains loaded in the COM+ environment and some of the objects may be kept in cache, even if no clients are connected to them. For this reason, you generally cannot recompile the COM library after using it, unless you use the MMC to shut it down or set a Transaction Timeout of 0 seconds in MMC.

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 Modules

The 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:

  • SetComplete tells the COM+ environment the object has finished working and can be deactivated, so that the transaction can be committed.

  • EnableCommit indicates that the object hasn't finished but the transaction should be committed.

  • DisableCommit stops the commit operation, even if the method is done, disabling the object deactivation between method calls.

  • SetAbort says the object has finished and can be activated but the transaction cannot be committed.

  • IsInTransaction checks whether the object is part of a transaction.

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+.


Even though COM+ configuration is much better than DCOM configuration, you are limited to computers with a recent version of the Windows operating system. Considering that even Microsoft is moving away from DCOM technology, before you build a large system based on it you should evaluate the alternative provided by SOAP (discussed in Chapter 22, "Using XML Technologies").

COM+ Events

Client 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.


Some critics say that Microsoft introduced this model only because it was difficult for Visual Basic developers to handle COM events in the traditional way. Windows 2000 provided a few operating-system features specifically intended for VB developers.

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):

  IMdInform = interface(IDispatch)
    procedure Informs(Code: Integer; const Message: WideString); safecall;

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:

  1. In Microsoft's Component Services console, select a COM+ application, move to the Components folder, and use the shortcut menu to add a new component to it.

  2. In the COM Component Install Wizard, click the Install New Event Class button and select the library you've just compiled. Your COM+ event definition will be automatically installed.

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:

  TInformSubscriber = class(TAutoObject, IMdInform)
    procedure Informs(Code: Integer; const Message: WideString); safecall;
procedure TInformSubscriber.Informs(Code: Integer; const Message: WideString);
  ShowMessage ('Message <' + IntToStr (Code) + '>: ' + Message);

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.

Click To expand
Figure 12.13:  A COM+ event with two subscriptions in the Component Services management console

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:

  Inform: IMdInform;
  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.

Previous Section Next Section



Copyright © 2004-2016 "Delphi Sources". Delphi Programming Guide
     Twitter     Facebook