Using an Existing COM Component

I l @ ve RuBoard

Using an Existing COM+ Component

We'll begin our odyssey through the world of serviced components by demonstrating how easy it is to consume a COM+ component from J#. A COM+ component can be written in almost any language, but our example will use Visual Basic 6.0 because it is quick and easy to do so.

Note

If you don't have Visual Basic 6.0 or don't want to follow along, skim through this section and resume reading closely at the section titled "Building a Serviced Component," where you'll learn how to create a serviced component using J#.


The FourthCoffee Components Revisited

Calling a COM+ component from managed code is not much different from using a regular COM component, at least as far as the programmer is concerned . You create a runtime callable wrapper (RCW) that acts as a proxy for the COM+ component, and you use the objects and methods exposed by the RCW just as you would ordinary managed components and methods .

The Visual Basic 6.0 project group FourthCoffee.vbg in the FourthCoffee folder contains an updated version of the Visual Basic FourthCoffee components used in Chapter 13. The CakeFactory class supplies the methods Feeds ­HowMany and CreateCake , and the Cake class exposes the size , shape, and filling of the cake as properties. This version of the project also uses enumerations for the cake filling and shape (just to prove that it can be done). An extra feature is the Baker class, shown below, which contains the BakeCake method. (We implemented a simpler version of this method in the J# example at the end of Chapter 13.)

 Public Sub BakeCake(ByVal howLongFor As Integer, ByVal cake as Cake) 

The Cake and CakeFactory classes are held in the FourthCoffee project, generating the ActiveX DLL FourthCoffee.dll. For reasons that we'll describe later, the Baker class is held in a separate project called FourthCoffeeBaker, generating FourthCoffeeBaker.dll.

Configuring the Fourth Coffee COM+ Application

If you examine the properties of the CakeFactory , Cake , and Baker classes, you'll notice that the MTSTransactionMode property is set to NoTransactions . (The default setting is NotAnMTSObject , which prevents an object from being able to use many of the COM+ services.) If you build the FourthCoffee and FourthCoffeeBaker projects, you can use the Component Services console to create a COM+ application and install and configure the FourthCoffee components.

A COM+ application is simply a container that hosts COM+ components and provides a configurable environment in which they can execute. As such, its role is similar to that of the EJB container in the J2EE platform. To save you a little time and effort, the FourthCoffee folder contains a Windows Installer package called FourthCoffee.msi. You can execute this package to create the Fourth Coffee COM+ application and install the FourthCoffee components.

Note

If you prefer to create the Fourth Coffee COM+ application by hand, you're most welcome to. The Component Services console is accessible through Control Panel. (Select Performance and Maintenance, and then select Administrative Tools). You can create a new COM+ application by expanding the Component Services tree to display the COM+ Applications folder and then choosing New, Application from the Action menu. You can install components in a COM+ application by expanding the Components folder and choosing New, Component from the Action menu. For the Fourth Coffee application, you should create components using FourthCoffee.dll (in the FourthCoffee folder) and FourthCoffeeBaker.dll (in the CakeBaker folder).


Figure 14-1 shows the components installed in the Fourth Coffee COM+ server.

Figure 14-1. The Component Services console showing the FourthCoffee components

COM+ allows you to configure component interfaces as supporting asynchronous, queued operations. Queued calls to methods defined by a queued interface are serialized and posted to an MSMQ message queue. (You must have message queuing installed on your computer for this to operate .) A listener component (part of the COM+ infrastructure) can be alerted when a message arrives so that it can deserialize the method call information contained in the message and invoke the appropriate method on the designated COM+ component. You don't have to write any extra code to support this functionality ”you simply set the appropriate properties using the Component Services console.

Figure 14-2 shows the Properties dialog box for the Fourth Coffee COM+ application, with queuing enabled. Selecting the Queued option will cause COM+ to create message queues (one public and several private ”their names are unimportant) for the component.

Figure 14-2. The Properties dialog box for the Fourth Coffee COM+ application, showing the queuing configuration properties

Methods of queued interfaces can take only input parameters and cannot have a return value. The BakeCake method of the Baker component is just such a method, so the _Baker interface generated by Visual Basic can be marked as a queued interface. To do this, you expand the interfaces folder under the Baker component, select the _Baker interface, right-click on it, select Properties, click on the Queuing tab, and make sure Queued is selected, as shown in Figure 14-3. (If you installed the Fourth Coffee COM+ application using the Windows Installer package, the Queued property will already be set.)

Note

When you create a component using Visual Basic 6.0, Visual Basic will automatically generate an interface for each component that has the same name as the underlying class but is prefixed with an underscore .


If the Queued property for an interface is disabled, this means that one or more methods in the interface do not meet the requirements for queued operations (no output parameters or return values are allowed, as you'll recall) and the interface will not support queuing.

Figure 14-3. The properties of the _Baker interface

You must consider one other important factor when you mark interfaces for queued operations: the serializability of method parameters. The BakeCake method takes a Visual Basic 6.0 Integer and a Cake object as arguments. For a queued method call to be bundled up into a serializable package and posted to a queue, the method call's parameters must also be serializable. The primitive automation-compliant data types (such as Integer ) are serializable, so they do not pose a problem and require no further thought. Classes, on the other hand, do require attention. A class created using the .NET Framework Class Library can be tagged with the Serializable attribute. However, in this example, the Cake class is implemented in Visual Basic 6.0, so the Serializable attribute cannot be applied. The solution is to enable the Persistable property of the Cake class and to implement the Class_ReadProperties and Class_WriteProperties subroutines. (We won't go into the details here.)

Once you've configured the Fourth Coffee application, it will be accessible through COM+ on the machine on which it is installed. If you want to use it from another computer, you must export the COM+ application to create a deployment package that can be copied and installed elsewhere. You can either export the entire COM+ application or create an application proxy (as shown in Figure 14-4) that can be installed on a remote client and used to access the application.

Figure 14-4. Creating a deployment package for the Fourth Coffee application

Note

If you want to create a package for installation on a computer running Windows 2000, you must select the Save Application In COM+ 1.0 check box.


Using the Fourth Coffee COM+ Application

The CakeClient class (which is available in the file COMPlusCakeClient.jsl in the COMPlusCakeClient project) shows a J# test harness that exercises the FourthCoffee components. To compile this class, you must create RCWs for the FourthCoffee and FourthCoffeeBaker DLLs. (You can use the COM tab of the Add Reference dialog box to do this, as we did in Chapter 13.)

The main method of the CakeClient class creates a new CakeFactory object and then calls the FeedsHowMany method, displaying the results in the console. (This is a synchronous method call.) The program continues, executing CreateCake to create a new Cake object using the cake factory and verifying that the size, shape, and filling properties of the cake have been set appropriately. Finally, the program creates a Baker object and executes its BakeCake method. However, the program makes use of the queued configuration of the Baker class, so the call to BakeCake is performed asynchronously. (The program will not be blocked while the cake is baking.) To access the Baker class through its queued interface, you must instantiate it using a queue moniker. The System.Runtime.InteropServices.Marshal class has the static BindToMoniker method for occasions such as this:

 Baker baker = (Baker)Marshal.BindToMoniker("queue:ComputerName=WHITERABBIT/new:FourthCoffeeBaker.Baker"); 

We'll refrain from describing the full syntax of COM+ monikers because it is beyond the scope of this book. Suffice it to say that the moniker specified will attempt to create a new FourthCoffeeBaker.Baker object and access it through a message queue on the computer called Whiterabbit (the name of the computer on which we installed and configured the Baker component ”you'll need to change this unless you have a computer with the same name). When the BakeCake method is invoked through the baker variable, the call will be queued and executed asynchronously.

Subscribing to a Loosely Coupled Event

Executing the BakeCake method asynchronously is fine, but it would be useful to know when the cake is ready. The usual mechanism would be for the Baker class to publish an event that is raised when the cake is ready, and allow clients to subscribe to this event. But the distributed, message-based nature of the COM+ interaction renders the original COM IConnectionPoint event model unsuitable. When using connection points, clients and servers have to query each other for information about events and sinks that might generate an unacceptable level of network traffic, and the mechanisms used require that the subscribing client must be running when the publishing server raises the event (which might not be the case when you use a COM+ queued interface). Instead, COM+ provides loosely coupled events (LCEs).

In the LCE model, you raise events by executing methods on a specially constructed event class, which is recorded in the COM+ catalog. (Each method will raise a different event.) A subscriber implements an interface that matches the event class and provides the code that the client will execute when the event is raised. Multiple subscribers can each have their own implementations of the event class. The subscriber must also be registered in the COM+ catalog as a COM+ application. An administrator can then use the Component Services console to tie a subscribing client to one or more event classes. The information about which clients subscribe to which event classes is held in the event store in the COM+ catalog. When a publisher calls a method defined by the event class, the COM+ events subsystem will query the event store to locate any subscribers. Each subscriber will then be instantiated , and the corresponding method will be invoked.

In the FourthCoffee example, the CakeEvents Visual Basic project defines an event class called CakeEventClass . This class has a single method named CakeBaked , which takes a Cake object as an input parameter. This method is used to raise the CakeBaked event from the BakeCake method in the Baker class. The method body itself is actually empty because the implementation will be supplied by each subscribing client.

The BakeCake method instantiates a CakeEventClass object and calls its CakeBaked method, passing the Cake object (which should now be cooked ) as the parameter:

 Dim cakeBakedEvent as CakeEventClass Set cakeBakedEvent = new CakeEventClass cakeBakedEvent.CakeBaked cake 

If you build the CakeEvents component (CakeEvents.dll), you can install it in the Fourth Coffee application using the Component Services console. You should install it using the Install New Event Class(es) option, as shown in Figure 14-5. (If you ran the Windows Installer package FourthCoffee.MSI earlier, this component will have already been created and installed for you.)

Figure 14-5. Installing a new event class in a COM+ application

Note

The FourthCoffeeBaker project, which contains the Baker class, contains a reference to the CakeEvents component defined by the CakeEvents project. The CakeEvents project in turn contains a reference to the FourthCoffee components in the FourthCoffee project. Visual Basic 6.0 forbids circular references between projects, so the Baker class must be placed in a separate Visual Basic 6.0 project from the Cake and CakeFactory classes.


Once the event class has been installed, expand the Interfaces folder under the CakeEvents.CakeEventClass component, right-click on the _CakeEventClass interface, and view its properties. You'll see the unique interface ID (IID) assigned to this interface (similar to the one shown in Figure 14-6 ”the IID generated might vary if you did not use the installer package to install the event class). Make a note of the IID because you'll need it when you implement a subscriber.

Figure 14-6. The properties of the _CakeEventClass interface, showing the IID

To subscribe to the CakeBaked event in J#, you must create a component that implements an interface with the same IID as the interface exposed by the event class. The CakeBakedEventSink class (available in EventSink.jsl in the COMPlusCakeEventSink project ”we added it to the same solution as the COMPlusCakeClient project for convenience) shows an example. The CakeBaked ­EventSink class implements the ICakeEventClass interface, which is also defined in EventSink.jsl. The ICakeEventClass interface contains the CakeBaked method (as specified by the CakeEventClass , created earlier in Visual Basic). Also, the ICakeEventClass is tagged with ComVisibleAttribute (this interface will be exposed to COM+ when the component is registered in the COM+ catalog) and has a GuidAttribute that is the same as that of the IID of the _CakeEventClass . (If the IID you saw earlier is different from ours, replace the GuidAttribute with your own value.) The COM+ infrastructure uses this IID to determine which classes can subscribe to the CakeBaked event (as explained later).

All .NET components that are deployed in COM+ applications must inherit from the System.EnterpriseServices.ServicedComponent class. You must add a reference to the System.EnterpriseServices.dll assembly to access the classes in the System.EnterpriseServices namespace. The ServicedComponent class provides the infrastructure that a .NET component will need when it interacts with COM+. (We'll come back to this later.)

The CakeBaked method takes a Cake object as its input parameter. This component was defined in Visual Basic and compiled as the FourthCoffee.dll ActiveX DLL. You might be tempted to add a reference to the DLL by using the COM tab of the Add Reference dialog box, as we did in earlier examples, but this approach has a problem: It generates an RCW that operates as a private assembly. When a .NET serviced component is registered in the COM+ catalog, all assemblies that it references must be signed with strong names; otherwise , registration will fail. So you must create a strongly named RCW manually and reference that instead.

You can build a strongly named RCW in several ways, but one approach I often take is to create a pair of keys using the Sn utility and then execute Tlbimp with the appropriate type library, specifying the keyfile option, which signs the resulting RCW using the keys in the designated file. It just so happens that the Visual Basic FourthCoffee project generates a type library called FourthCoffee.tlb that can be used by Tlbimp. Make a copy of this file in a convenient place (the WINDOWS\Temp folder for example) and execute the following commands from the command line to create the signed RCW called FourthCoffee.dll:

 sn k FourthCoffee.snk tlbimp FourthCoffee.tlb /keyfile:FourthCoffee.snk 

Note

If the FourthCoffee components are running, you'll be denied access when you execute Tlbimp. Stop the FourthCoffee components using the Component Services console: Right-click on the Fourth Coffee COM+ application and choose Shut Down from the shortcut menu.


If you're going to reference this RCW from several applications, you might want to place it in the Global Assembly Cache (GAC):

 gacutil /i FourthCoffee.dll 

For consistency, you can create a signed version of the FourthCoffeeBaker RCW, using the FourthCoffeeBaker.tlb type library generated by Visual Basic (which you'll find in the CakeBaker folder):

 sn k FourthCoffeeBaker.snk tlbimp FourthCoffeeBaker.tlb /keyfile:FourthCoffeeBaker.snk gacutil /i FourthCoffeeBaker.dll 

Back in the COMPlusCakeEventSink project, you should add a reference to the signed version of the FourthCoffee assembly. (In the References dialog box, click on the .NET tab and use the Browse button to locate FourthCoffee.dll in the WINDOWS\Temp folder.) You should also update COMPlusCakeClient project to remove any references to the unsigned RCWs (FourthCoffee and FourthCoffeeBaker) and reference the signed versions instead.

The COMPlusCakeEventSink assembly itself should also be strongly named. The assembly is signed using the keys in the file CakeEventSink.snk, as indicated by the assembly level AssemblyKeyFileAttribute . By convention, this attribute is specified in the AssemblyInfo.jsl file created with each project by Visual Studio .NET (the purpose of this file is to provide a convenient place to specify assembly-level attributes), but we added it to EventSink.jsl and removed AssemblyInfo.jsl to keep everything in one place.

The implementation of the CakeBaked method in the CakeBakedEvent ­Sink class displays a message box indicating that the cake has been baked and outputs the details of the cake. The call to ReleaseComObject ensures that the cake object is released in a timely manner. You can compile this class, which produces the assembly COMPlusCakeEventSink.dll.

Note

Message boxes can be useful for providing some visual feedback when you test serviced components, but you should not use them in a production environment ” mainly because they might be displayed on the computer that's hosting the serviced component rather than on the client that's calling the serviced component. (It depends on how the hosting COM+ applications are configured.) Even if the message box is displayed on the client computer, this approach is still not good practice for production applications because the COM+ application might be configured to run as a service and operate without a GUI. Furthermore, if the event class is not configured to fire events in parallel (the default situation), a message box that's waiting for user acknowledgement might block other subscribers from being notified!


The next step is to create a new COM+ application using the Component Services console and install the CakeBakedEventSink component. (We haven't supplied a package for this, so you'll have to do it yourself!) To keep resource use to a minimum, create a COM+ Library application. You can name the application anything you like. (We used "Fourth Coffee Client.") Once you've created the application, you can install the CakeBakedEventSink component from COMPlusCakeEventSink.dll.

You can then attach this component to the CakeBaked event. To do this, expand the COMPlusCakeEventSink.CakeBakedEventSink component to display the Subscriptions folder, right-click on it, and choose New, then Subscription (as shown in Figure 14-7) to launch the COM+ New Subscription Wizard.

Figure 14-7. Adding a new subscription to the CakeBakedEventSink component

On the wizard's Select Subscription Method(s) page, you'll see a list of the interfaces and methods implemented by the CakeBakedEventSink component. Scroll to the bottom of the list and select the CakeBaked method in the ICakeEventClass interface, as shown in Figure 14-8. Click Next to continue.

Figure 14-8. The interfaces and methods implemented by the CakeBakedEventSink component

On the Select Event Class page, you'll see every event class that implements an interface with the same GUID as that used by the ICakeEventClass interface ” CakeEvents.CakeEventClass in this case, as shown in Figure 14-9. To subscribe to the events represented by an event class, select it and click Next.

Figure 14-9. The Select Event Class page

The final page of the wizard allows you to give the subscription a meaningful name and enable the subscription. (You can also enable and disable subscriptions using the Component Services console.) Figure 14-10 shows the Subscription Options page filled in. Click Next, and then click Finish.

Figure 14-10. The Subscription Options page

The COMPlusCakeEventSink assembly needs to be available to the Visual Basic runtime, so copy the file COMPlusCakeEventSink.dll to the folder \Program Files\Microsoft Visual Studio\VB98 ( assuming you have Visual Basic installed in the default location). When you execute the COMPlusCakeClient program, the cake will be created and its details displayed in a console window, as before. However, 30 seconds later (we tweaked the BakeCake method to wait in seconds rather than minutes ”you can change it if you really want to wait half an hour !) the BakeCake method will raise the CakeBaked event and the message box shown in Figure 14-11 will appear.

Figure 14-11. The message box displayed by the CakeBaked event handler

Note that the event handler ran and displayed the message box even though the COMPlusCakeClient application already finished. The COM+ event subsystem creates a new instance of the CakeBakedEventSink object in the COM+ process that executes the Baker object whenever the event occurs.

Note

A subscribing component will receive every notification of an event raised by the publisher, no matter which client invoked the action that caused the publishing component to raise the event. (There is no direct link between a client application and a subscriber.) However, once you've created a subscription, you can adjust the properties of that subscription and apply a filter so that the subscriber is notified of an event only if it is relevant. (The details of event filtering are beyond the scope of this chapter.)


I l @ ve RuBoard


Microsoft Visual J# .NET (Core Reference)
Microsoft Visual J# .NET (Core Reference) (Pro-Developer)
ISBN: 0735615500
EAN: 2147483647
Year: 2002
Pages: 128

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net