COM Component Services

[Previous] [Next]

As you can see in Figure 15-1, the core of COM+ is the integration of an improved COM with an improved MTS. Both COM and MTS have been very successful technologies, so this isn't a bad start at all. Tom Armstrong, author of several books, including Active Template Library: A Developer's Guide (IDG Books Worldwide, 1998), wrote an article about this in the February/March 1999 issue of Visual C++ Developer's Journal. He used the Beta 3 version of Windows 2000 as the basis for his article, which he called "COM + MTS = COM+: Next Step in the Microsoft Component Strategy."

Figure 15-1. COM+ is the result of merging an improved COM with an improved MTS.

The merger of COM and MTS is important because behavior that's specific to MTS objects becomes normal behavior for most COM+ objects. This simplifies your work as a developer in ways we'll describe in this chapter, and that's important by itself. But being the result of the merger between an improved COM and an improved MTS isn't all that COM+ is—far from it. Microsoft has added other important component services to COM+, and we'll tell you briefly about some of them in this chapter.

Queued Components

Queued components (QC) is the first and probably most important of the component services added by Microsoft to COM+. The purpose of QC is to make Microsoft Message Queue Server (MSMQ) easier to use and, most important, easier to program. If you want to take advantage of MSMQ without using QC, you'll have to use a programming model that's very different from the programming model you use for the rest of your application. You also need to use low-level API calls to make MSMQ do a good job for you. QC change all that and allows you to use the same programming model for sending MSMQ messages that you would for the rest of your project. Rather than write a bundle of API calls, you set a few attributes on the component you want to send messages to. Then you create the object you want to send messages to in a different way, described later in this chapter. With QC, this is all you have to do to take advantage of MSMQ; set a few attributes and change one line of code.

Semiannually we run a series of seminars in Sweden's major cities. Before the fall of 1999, we used to call these seminars Client Server Training; as of the fall of 1999, we changed the name to WinDNA Training. The subject of the Fall 99 seminars was Windows 2000 and COM+, and we asked the approximately 600 attendants which of them had used MSMQ. It turned out that only about 10 or 12 out of the 600 had. This is pretty low for a country such as Sweden, well known for its eagerness to take advantage of new technologies. So we felt we had to ask ourselves the following question: "Is the reason for this low number that MSMQ is too difficult to program against or use, or is it because there's no real need for a messaging server?"

In an attempt to glean an answer to our question, let's take a look at a typical problem for which you might consider using MSMQ, and for which most developers obviously don't. Studying such a problem might give us at least part of the answer. "Would MSMQ help solve the problem or not?" Figure 15-2 shows an overview of such an application.

click to view at full size.

Figure 15-2. When an order is received, the client calls an Order object to insert the order in the database. The Order object then calls a Shipment object to insert the order in the shipment database. All this is scoped within the same transaction.

A design such as the one in Figure 15-2 has clear advantages. Because the insertion in the order database and the insertion in the shipment database share the same transaction, you're guaranteed that every order received is inserted not only in the order database for safekeeping and possibly as a basis for confirming the order but also in the shipment database for shipment purposes. This is a good thing; you need such a guarantee—it wouldn't do for an order to be received, entered, and confirmed but never shipped to the customer.

The design also carries with it a few disadvantages, the major one being that the shipment component and the shipment database must be available when the order is entered in the order database. If the shipment server is down, or if there's a problem connecting to it, you can't even get the order into the order database: the entire transaction rolls back—it's an all-or-nothing-at-all proposition. You'll have to postpone entering the order until you can get connected to the shipment server again. Such a restriction probably isn't reasonable or productive. A better scheme would let you insert the order in the order database now and in the shipment database later, although in good time for it to be shipped when it's supposed to be. The only snag is that such a scheme must give you the same kind of guarantee that the order will be eventually inserted in the shipment database that the scheme in Figure 15-2 gives you.

Figure 15-3 is the first of a series of figures that together show you such a scheme, using MSMQ to send a message from the Order object to the Shipment object asking for the order to be inserted in the shipment database. In Figure 15-3, a transaction is used to ensure that the order winds up not only in the order database but also as a message to the shipment component. This message is inserted in an MSMQ outbox that guarantees eventual delivery of the message to the shipment component.

click to view at full size.

Figure 15-3. This is the first transaction in a series of three. The Order component enters the order in the order database. It also puts a message to the Shipment component in an outbox. The transaction guarantees that the order winds up in both places or in neither of them.

Figure 15-4 shows how MSMQ takes the message from the order server's outbox and sends it to an inbox in the shipment server. This work is done in a second transaction, which guarantees that the message is really delivered to the shipment server, but also that it's sent there once and never more than once.

click to view at full size.

Figure 15-4. The second transaction guarantees that the message is eventually transferred from the order server to the shipment server and that it's sent exactly once—no less, no more.

In the next step, which could possibly be the last step of the process, a third transaction takes the shipment message from the inbox and inserts the order in the shipment database, which is shown in Figure 15-5.

click to view at full size.

Figure 15-5. In the third transaction, the shipment component takes the message from the shipment inbox and then sends the order to the shipment database.

Figure 15-5 also shows the entire set of transactions. The first transaction guarantees that any order inserted in the database is also put in an MSMQ outbox as a message to the shipment component. The second transaction makes sure that the message is sent exactly once from that outbox to a corresponding inbox in the shipment server. The third transaction takes the message from the inbox and adds the order to the shipment database. If the infrastructure works, and if the shipment database accepts the order, the third transaction concludes the entire process. But what if something goes wrong? Figure 15-6 gives a possible answer to that question.

click to view at full size.

Figure 15-6. When the shipment component has inserted the order in the shipment database, or failed to do so, it uses MSMQ to send a message back to the order server, informing it of the successful or unsuccessful insertion of the order in the shipment database.

Figure 15-6 shows how the shipment component can send a message back to the order server, informing it of the success or failure of inserting the order in the shipment database. This is the final step of the entire transaction. If the shipment component or database can't accept the order, something has to be done about it. You can't have a situation in which the order database accepts an order, perhaps confirming it to the customer, and the shipment database won't have it. Therefore, you need some kind of callback system, in which the shipment server can inform the order server of any problems.

This situation is like using a check to pay for goods received. When the shop accepts your check, the purchase is concluded. You get the merchandise and a receipt for your payment. But when your check bounces at the bank, the shop probably comes back to you and asks you to solve the problem or return the goods. What seems to be one transaction is really three: the first one occurs when you pay with your check; the second one occurs when the check bounces; the third one occurs when you give the shop real money or return the goods.

Chances are you'll never hear about it if your check doesn't bounce. Only if it bounces does the shop come back to you. You can design a similar system for your queued transaction. In fact, you have three possible strategies to choose from:

  • The first strategy is the optimistic one. Using it, you completely trust the infrastructure and the software. "In good time, the order is inserted in the shipments database, no question about it. I don't need to be told about it. No receipt needed here."
  • The second strategy is pessimistic. "I want to be told about success as well as failure after the shipment component has inserted the order in the shipment database. I won't sleep until I know that everything is OK."
  • The third strategy represents the middle ground. If you want, you might call it the realistic strategy. You trust the infrastructure and the software, but you're old enough to know that if something can go wrong, it will.1 Being a trusting person, you don't want to be told when the order is successfully inserted in the shipment database. Being a tried old-timer, you do want to know if and when anything goes wrong; if so, you want a message to be sent back to the order in the order database, but only if there's a problem that you need to react to.

The only trouble with this queued scenario, shown in Figures 15-3 through 15-6, is the difficulty in programming the queue and the messaging. You must learn a different programming model, and you must make lots of low-level API calls to make MSMQ work well for you. At least, so it was before COM+ and QC. Now your effort has been reduced to setting a few attributes of the component that's supposed to receive the message and to using the GetObject method with a moniker rather than the CreateObject method when creating the object the message is supposed to be sent to.

A moniker is a special kind of COM object that knows how to locate another COM object. You can read more about monikers in Understanding COM+ or Inside COM+ Base Services. To open a queue to a COM object for asynchronous rather than synchronous COM or DCOM communication, you use two monikers, new and queue. The syntax for using GetObject with these two monikers is as follows:

Set objVar = GetObject("queue:/new:ProgId")

Say that you want to open a queue to a shipment component, defined in a Microsoft Visual Basic project named Shipments. The following code line shows how you could achieve this:

Set objShipment = GetObject("queue:/new:Shipments.Shipment")

You'll probably not believe it, but this is the only code change you'll have to make when moving from ordinary COM or DCOM traffic to message-based communication. The rest is achieved by setting attributes. Figure 15-7 shows the first two attributes you have to set.

Figure 15-7. The COM+ application in which your code component resides must be able to receive calls from a queue, and it must be able to listen to that queue to find out when messages come in.

Figure 15-8 shows the third and last attribute you have to set to make an interface accept queued messages for its component.

Figure 15-8. In a COM+ application configured to listen to a queue and accept queued messages, at least one component interface must also be configured to accept queued messages.

That's all there is to it. The queued component is now able to receive calls either over DCOM or via MSMQ. If its client opens a connection using the CreateObject method, the component accepts ordinary DCOM calls. If the client opens the connection using the GetObject method and the two monikers mentioned, the component accepts calls through MSMQ.

To tell the truth, though, there are a couple of other things you have to take care of. Methods able to receive MSMQ calls must not return any information through output parameters or return values. After all, when the component receives the message, there's no client to return any values to. So, using Visual Basic terminology, such a method must be a Sub because a Sub doesn't return anything. It must also accept every call argument ByVal because such an argument is never returned to the client.

We're sure the queued components of COM+ will solve many problems in distributed computing. If you think about it, you'll probably find many situations in which queued components make more sense than connected method calls. Using our architecture, you should try, for every transaction, to establish the critical path of the transaction. What must be done when the transaction is first introduced? In the case of the order insertion in Figures 15-3 through 15-6, the only thing that's necessary to do up front is to insert the order in the order database. Putting it in the shipment database can wait. That being the case, only the insertion in the order database should be done in a connected fashion. Sending the order to the shipment database should be done with a message through MSMQ in a separate transaction. Partitioning the transaction in this way improves at least the perceived performance of the transaction. It also improves availability because you can enter the order even when the shipment server is down.

If you want to know more about queued components, the only published book that we know exists right now is Understanding COM+. An obvious other source for such information is Microsoft's Web site at http://www.microsoft.com/com/tech/complus.asp . Given the growing importance of COM+, bundles of books should come out from several publishers during the coming months and years. So start reading whatever you come across on the subject. By the time you read everything currently available on the subject, no doubt somebody will have written more about queued components for you to read. Enjoy!

Loosely Coupled Events

Loosely coupled events (LCE) is another new component service that's included in COM+. LCE recognizes the need in an enterprise to publish information about important events that have occurred. Before the arrival of COM+, we thought about COM events as requiring two components to be tightly coupled to each other. An event happening in one of the components is signaled to the other component, making it possible for the component receiving the signal to react to it.

A typical tightly coupled example is the event that fires when a user clicks on a command button, making it possible for the form that contains the command button to react in a certain way. The form must be connected to the command button when the event occurs; otherwise, the form can't react to the event. With "old-fashioned" COM, this is no problem. A form that's not connected to a command button contained in the form is hardly conceivable.

But users, enterprise users in particular, have other needs too. When certain things happen, people or components would like to be told even if they're not connected at the time of the event, allowing them to react individually to the event. Before COM+, any organization in need of such publishing of events would have to create its own infrastructure for the publishing of event information. COM+ provides such an infrastructure, allowing components to subscribe to information about occurring events published by other components. The publisher doesn't even have to know anything about the subscribers, and the subscribers don't have to be connected when the event occurs. They are "loosely coupled" to each other in an events database, using the COM+ Event Service to distribute information about the event to subscribers.

A subscriber is always a component, and it must expose the same interface the publisher uses to inform an event class that the event has happened. The event class in turn informs the event database of the event; the COM+ Event Service makes sure that every subscriber gets the information when the subscriber is ready to receive it. Messages from publishers to their event class can be queued, and so can messages from the COM+ Event Service to subscribers.

Our architecture implicitly supports loosely coupled events, but we don't currently give any examples of how you can use them. If you want more information about loosely coupled events, you should investigate the same sources we mentioned in the section about queued components.

Object Pooling

In Chapter 14, "Using Microsoft Transaction Server," we told you about object pooling. In this chapter, all we have to add to the information given to you in Chapter 14 is that object pooling is available in COM+. What we told you about the requirements for object pooling and the limitations of Visual Basic components still applies. Components created in and compiled by Visual Basic 6.0 won't pool. What will happen in this respect with components created in and compiled by the next version of Visual Basic is written in the stars. Please understand that this doesn't mean that you can't use object pooling in our architecture. The architecture is in no way language dependent, even though all our examples are written in Visual Basic. If your application contains components that take long to create, and if the performance of your application doesn't meet your goals, you should absolutely consider the use of C++ to make it possible to pool those components' objects.



Designing for scalability with Microsoft Windows DNA
Designing for Scalability with Microsoft Windows DNA (DV-MPS Designing)
ISBN: 0735609683
EAN: 2147483647
Year: 2000
Pages: 133

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