Designing Queued Component Interfaces

When a client makes calls to a queued component, it interacts with the recorder provided by COM+. No actual calls to the real object occur. So, at the time of the call, the client has no way to receive output from the method, nor can it tell whether the call succeeded or failed. Consequently, when you design an interface to be supported by a COM+ queued component, you must avoid any outgoing parameters on any interface method.

Specifically, do not use any [out], [in,out], or [retval] IDL attributes on your method parameters. When you import a component into the Component Services Explorer, COM+ inspects the interfaces supported by that component, and if it detects an output attribute, COM+ disables the queuing option for that interface.

If you develop your COM+ component using Visual Basic 6.0, you do not have direct access to your component IDL. Normally, this lack of access would not be a problem. However, Visual Basic, by default, treats method parameters as [in,out] parameters. If you expect your component to be accessed as a queued component, you have to explicitly use the Visual Basic ByVal attribute on your method parameters.

Tip

In the next version of Visual Basic, Visual Basic.NET, all parameters are, by default, passed in by value instead of by reference. See Chapter 10 for more information.

A different kind of a parameter returned from a method is its return value. You should avoid using custom HRESULT codes to indicate particular failure cases. The client only receives the HRESULT from the recorder, indicating the success or failure of recording the call. When your object executes, its HRESULT codes are delivered to the player, which does not understand your custom semantics. COM+ does not require you to stick to the standard HRESULT codes, but there is no point in not doing so.

Another restriction on queued component interfaces is that the client cannot pass in a pointer to another COM object. The reason is obvious—when the actual call takes place later, there is no guarantee that the object passed in as a parameter is still around.

Implementing a queued component implies more than just a few method parameters restrictions and clicked checkboxes on the Component Services Explorer. It really means a change in your design patterns and programming model.

The only way to pass in COM objects as a method parameter to a queued object is if the object you pass in supports the interface IPersistStream . IPersistStream is a standard interface used for object serialization, defined in the early days of OLE2 and COM. Objects that support IPersistStream can serialize their state into a COM+ provided stream and reconstruct their state out of such a stream.

Whenever you pass a COM object as a method parameter, COM+ queries it for IPersistStream. If the object supports it, COM+ calls IPersistStream::Save( ), passing in a pointer to an IStream object. The input object saves its state to the stream. The recorder stores the saved state information in the message sent to the queued component application queue. When the player retrieves the message, it creates a stream object from the message and calls IPersistStream::Load( ) to initialize the object to the state it was in when the call was made. It then invokes the call on the component, passing in the input object as parameter.

When you design an interface used by a queued component, you can use a new IDL extension, an interface attribute called QUEUEABLE , to denote it as an interface used by a queued component. The mtxattr.h header file defines this extension.

Example 8-1 shows the IShipment interface definition again, this time using the QUEUEABLE attribute.

Example 8-1. Using the IDL QUEUEABLE attribute to denote an interface as queued-components compatible

#include "mtxattr.h" // For QUEUEABLE
[
   object,
   uuid(97184D0F-F7EF-413A-8C6D-C1745018B2E9),
   dual,
   pointer_default(unique),
   QUEUEABLE 
]
interface IShipment: IDispatch
{
   [id(1)] HRESULT ShipOrder([in]DWORD dwOrderNumber);
};

This attribute autoconfigures the interface as Queued when you import a component that supports the interface into the Component Services Explorer. This autoconfiguration saves you the trouble of doing it yourself. The attribute has no semantic meaning for the MIDL compiler; it will not stop you from defining [out] parameters on an interface marked QUEUEABLE. Only COM+ examines this attribute.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset