Let’s see what protection MTS gives. We’ll take our
component, and set it up so that it runs under MTS. We do this by using the MTS Explorer. This has gone through a number of incarnations, and is now happily ensconced as a plug-in to the increasingly ubiquitous Microsoft Management Console. SimpleNegotiator
Incidentally, if you haven’t come across MMC before, take a look — we’ll be writing our own component management plug-in later on in the book, when we covered managing, monitoring and control in Chapter 10.
This is a good point to take a look at Oleview (preferably using Expert View, and at the entries under the Automation Objects folder) at our Negotiator object. You should see that it is currently an in-process server with implementation path something like:
...\Chapter 5\SimpleNegotiator\Debug\SimpleNegotiator.dll
That will soon change...
Setting up a component to run under MTS is child’s play. First of all, you need to define a package. Packages are groups of components that usually work together, and have a common security requirement. Defining a package (by right-clicking on the Packages Installed option) is basically a question of specifying that you want to create a brand new package and then giving it a name (say, Negotiator). You also need to specify which user identity the package is to run under; this should have just the minimum rights needed to carry out the negotiation process. This would mean having access rights to the
and kidnap1
databases in SQL Server.kidnap2
You now need to add your component to your new package. You can just drag the DLL to the right pane of MTS Explorer when Negotiator | Components is selected. Alternatively, you can right-click on Components, select New -> Components and ask the MTS Explorer to install or import a component.
Having done this, you should see your new component appear in the list of components for the
package:Negotiator
Keep an eye on that ball with the cross on it — it will play tricks later.
Back in Oleview,
has miraculously mutated from being an in-process server to a local server with this implementation path:Negotiator
C:\WINNT\System32\mtx.exe /p:{EAE7E2CE-A7A5-11D1-B0F0-0040951082F7}
The UUID here is the UUID identifying the package, by the way.
All the components that have been registered with MTS run under the control of the transaction server proxy,
. It's mtx
that requires that your components be part of a DLL, and use standard class factories and standard marshaling. mtx
Strictly speaking, you don’t have to use
; you can run your component in the client’s process if you use the MTS Executive, mtx
, as your proxy. However, we’re interested in distributed systems here.mtxex.dll
OK, so we have now brought our component into the ambit of MTS. All we have to do now is tell MTS what to do about automatic transactions. If we look at the Transaction tab under Properties for the component, we see that we have four choices:
The second case is the most straightforward. If this is set, every time a component is instantiated, a new transaction is started. If the first choice is set, MTS ensures that the component is always running within the context of a transaction, but only creates a new one if necessary (in other words, if there isn't a context already available). In the third case, if there is a current transaction context, it is passed on to the component, but otherwise a new transaction isn’t started. Finally, in the fourth case, the component is treated just as if it was running as a DLL outside of MTS. We’ll find out more about transaction contexts in the next section.
We’ll choose the first option for our component.
Having done this, let’s try repeating some of the tests that we carried out on the component before we put it into MTS. You shouldn’t see any difference, other than the amusing feature that whenever our component is instantiated, the ball with a cross on it starts to spin! It’s actually quite a useful visual cue that something is going on. Once you’ve run the client a few times, take a look at the transaction statistics — you should see that for every test run you carried out, a transaction successfully completed.
We still haven’t successfully managed to tie the two halves of our transaction together, however. If the second half fails, the first half still goes blindly ahead. So what is MTS doing for us here? (Apart from gathering statistics for us, that is.) Well, the fun starts if we put our divide by zero back into the
method. Now look what happens: the method fails to complete, and an aborted transaction appears in our statistics! DealWithKidnappers()
What’s more, if we take a look at the state of our databases after our attempted transaction, we’ll find that no changes have taken place. So, even without putting any knowledge of the transaction into our component, we can see that MTS is providing a considerable degree of protection against software failure. It’s just possible to think that, even without any fully-blown transaction content, you might consider bringing your components under MTS control anyway.