MSMQ as a Transport Layer

Back in Chapter 3, we looked at various ways of optimizing DCOM for use over a seriously wide area network. If you remember, we had an order entry system located in Tierra del Fuego, and a client base in Ulaanbaatar. What I’d like to explore now is how we could bring MSMQ to bear on the problem.

One of the problems with DCOM (as presently implemented) is that it is entirely synchronous. Every time your client in Ulaanbaatar invokes a method in Tierra del Fuego, it has to sit and wait until the method completes until it can move on to the next operation. Most of the time this is pretty acceptable; however, every now and then, we come across an application that can’t wait — or perhaps doesn’t even need to wait. So the connection between the client and the server has to become a little looser.

For once, we find here that our old friend and rival CORBA has got there ahead of us. In the CORBA IDL definition, we can specify a method to have the attribute

oneway
. If you specify a method as having this attribute, the client doesn’t wait for the server to complete before moving on. A moment’s thought will tell you that if you specify a method as being
oneway,
it can’t have any
[out]
parameters, but that’s OK, because we can get outputs back from the server as events. This looks suspiciously like re-inventing asynchronous programming, callbacks and all, and frankly, it is. The current buzzword to describe this is Real-Enough Time.

Just to recap, our orders are represented by

Order
objects, with – at the moment – a single interface,
IOrder
. This interface has five properties, all strings:
CustomerID
,
Title
,
Artist
,
Label
and
Price
. There is also a single method,
Submit()
, which actually enters the order into a “database”

(actually a single-record file). What we’re going to do is implement all the properties as local methods (so that all validation is carried out locally), and then make the

Submit()
method one-way asynchronous. We’ll use MSMQ queues to communicate between the client and the server, so what we’ll end up doing is serializing our orders somehow, encapsulating them as MSMQ messages, and then sending them over MSMQ to a queue located on the server. We’ll also need to set up some kind of stub process sitting on the server machine to take the messages off the queue as and when they come in.

Now we could do all of this by means of custom marshalling. If we did this, we’d probably end up implementing

IOrder
in three places: in the COM server, in the proxy and also in the stub process. This ends up looking extremely inelegant, and there’s actually a much better way of doing it. It turns out that MSMQ is rather good at sending and receiving objects.

This is what we’re going to do. We’ll start off by creating a standard queue on each machine, called async. We’ll create a workspace called

AsyncOrder
, and add a project called
AsyncOrder
underneath it. This project will start off like the
SerialOrder
project that we had in Chapter 3. However, this time, it’s implemented as a DLL. We'll also need to ensure that
IPersistStream::GetSizeMax()
is fully implemented, just as it was in the
MarshalOrder
project. We'll take this as our starting point and examine the changes that need to be made from this point on.

Later on, we’ll create a second project in the workspace, called

AsyncOrderStub
and then we’ll deal with the stub process. All of the code here can be downloaded from www.wrox.com. Right now, let’s concentrate on the DLL.

© 1998 by Wrox Press. All rights reserved.