Objects, Components, and Transactions
David Chappell - October 1997
Component-based development looks like the next big wave in software
engineering. Microsofts COM is the most widely used component
model today (in fact, depending on how you define "component",
it may be the only widely used component model today). So far, components
have mostly been popular for building client applications, but thats
about to change.
Components for servers are here, and building serious server apps, whether or not components are involved, often requires transactions. Transactions have long been a mainstay of business computing, and today, objects are, too. It shouldnt be surprising, then, that these two technologies need to be united in some way. In the world of COM, that unification happens in the Microsoft Transaction Server (MTS).
MTS is more than just transactions plus objects, however. Among
its several innovations, it requires creating applications as COM
components. As Ill explain, this turns out to have some very
Im going to assume that you know the basics of objects, but transactions might not be so familiar. Defined narrowly, a transaction can be thought of as a group of changes (e.g., to one or more databases) with the property that either all of those changes happen or none of them do. If an application needs transactions, its certainly possible for the developer of that application to write the code himself to ensure this property. Because this requirement shows up so often, though, and because it can be surprisingly hard to get right, various vendors provide software products called transaction processing monitors (or just TP monitors) that provide standard solutions. In the IBM mainframe world, for example, the venerable CICS is the leading example, while products like BEAs Tuxedo, NCRs TopEnd, and Transarcs Encina provide the same kinds of solutions for Unix and Windows NT servers. Microsofts MTS fits in this same category, although its an NT-only solution.
An application that needs transactions very likely needs other
services, too. For example, the application will probably need to
scale to handle a large number of clients. While this doesnt
have much to do with transactions per se, its nevertheless
a commonly required service for enterprise applications, and so
TP monitors usually provide services that can improve application
Transactions and Objects
A typical TP monitor provides applications with several standard API calls. The usual pattern is for an application to make some kind of call to begin a transaction, then perform the work that makes up the transaction (such as changing records in one or more databases), and finally to end the transaction by asking the TP monitor to either commit the transaction (making all the changes permanent) or abort it (rolling back all the changes). Accomplishing this requires that the TP monitor work together with the database(s) in which those changes were made.
The most straightforward way to make this object-oriented is to express all of these interactions as method calls on appropriate objects. Rather than just calling an API function to start a transaction, for example, an application might create a new transaction object, then, when its work is finished, invoke appropriate methods on that object to commit or abort the transaction. This is essentially what the OMGs Object Transaction Service (OTS) does. Microsoft does this, too, in something called OLE Transactions. OLE Transactions is broadly analogous to OMGs OTS, but the objects defined by OLE Transactions are, of course, COM objects (in fact, the use of the "OLE" tag here is one of the last vestiges of the days when this label was assigned to anything that used COM).
A CORBA-based TP monitor typically exposes the OTS objects to clients, allowing them to invoke methods in the familiar pattern of "Begin Transaction, Do Work, Commit or Abort Transaction". Interestingly, MTS doesnt do this. In fact, MTS doesnt even implement OLE Transactions itself. Instead, the objects defined by this spec are mostly implemented in something called the Distributed Transaction Coordinator (DTC). DTC runs in a separate process from MTS applications, and it was actually released before MTS. Its really DTC that acts as the transaction coordinator when committing or rolling back the changes made by an application. MTS is just a user of DTC, relying on it to do the hard work of handling transactions.
Okay, so then what does MTS do? Well, as described earlier, TP monitors typically provide services that make it easy to write scalable applications, and MTS offers quite a bit here. MTS also provides an interface for applications to use transactions, although it passes the actual work involved off to the DTC. The interface MTS provides is simpler than the raw OLE Transactions interface, which is a good thing. But theres something even more important about the way MTS changes the interface applications see. To understand what that is, we need to think about more than transactions and objects; we need to think about transactions and components.
Transactions and Components
Theres already a significant market in client-side components, nearly all of which today are ActiveX controls (although JavaBeans will surely acquire some market share). Components for servers can also be very useful. Imagine, for instance, being able to buy standard components for order entry or funds transfer or other common operations, then building applications around them. Its unquestionably an appealing idea.
A primary goal of MTS is to provide a container for standardized server components, thus allowing this kind of market to exist. And since these sorts of components will often need transactions (to, say, atomically transfer money between two accounts), it makes sense to use a TP monitor as their container.
But by their very nature, components are meant to be used in diverse ways, being combined into applications in ways unforeseen by their creators. If those components use transactions, the standard "Begin Transaction, Do Work, Commit or Abort Transaction" model wont work. To understand why, imagine you have a component that knows how to take online orders, making changes to several databases as needed to fill those orders. Suppose that you also have a component capable of transferring money from one bank account to another, e.g., from the account of the company placing an order to the account of the company thats filling the order. Each of these components requires a transactionotherwise, only some of its changes might occur, leaving the data in an inconsistent state.
But each of these components might be useful either on its own or in concert with other components. If each component were always used alone, the traditional "Begin Transaction, Do Work, Commit or Abort" structure would work just fine. But what if somebody wants to combine both components into a single transaction, so that placing an order and getting paid are one atomic operation? If each component contains its own Begin Transaction request, this becomes problematic.
The solution adopted by MTS is to not allow a component to explicitly control when a transaction begins. Instead, each component can be administratively configured to require a transaction. When a client creates a component (i.e., a COM object) that requires a transaction, MTS automatically starts one. If that component just does its work, then commits or aborts the transaction, MTS carries out the components requestthis component has its own transaction. If this component creates another component, though, and that new component also requires a transaction (such as when the two components described earlier are used together), MTS can automatically include the changes made by this new component in the transaction that already exists. When this second component commits or aborts its work, MTS notes this but doesnt end the transaction. Not until the parent component, the one originally created by the client, decides to commit or abort does MTS end the transaction. If both components asked to commit, the transaction commits. If either one chose to abort, however, all of the changes made by both components are rolled back.
This approach allows the same component binary to be used in its own transaction or combined with others into a single transaction. For people accustomed to the traditional model, having no Begin Transaction call can seem weird. But get used to itthe marriage of components and transactions is looking very stable.
Microsoft vs. Everybody Else
Microsoft isnt the only vendor who understands the importance of combining components with transactions. They are well ahead in this game, however. MTS shipped in late 1996, while products supporting Enterprise Java Beans, the primary competing technology for transactional components, have yet to appear. Furthermore, MTS (and DTC) are free, while their competitors expect (not unreasonably) to make a profit on their products. And at Microsoft, the MTS and COM groups have been merged, implying that support for transactions will eventually become an even more fundamental part of the software infrastructure in the Windows NT environment.
But MTS only runs on NT. This is a significant limitation for a couple of reasons. First, NT isnt available yet for truly large systems, which means that big transaction-oriented applications cant be written using MTS. But perhaps more important, applications that use transaction monitors such as MTS tend to be mission-critical, bet-the-business kinds of apps. When youre creating this kind of application, it pays to be conservative. How long will it be before people really trust NT?
Still, MTS is remarkably innovative, and its likely to become the most common container for server-side transactional components. Its limitations are really NTs limitations, and one could argue that those limits stem more from NTs relative youth than from any intrinsic flaws in the operating system. Its hard not to believe that MTS will become a very widely used technology over the next few years.
The traditional take on Microsoft has always been that they dont innovate. Like the IBM of old, they wait for others to invent good ideas, then create their own version of those ideas, relying on sheer market power to win. But this perspective is getting harder and harder to defend. COM itself is an innovation, one that other vendors have been doing their best to imitate. And the idea of merging transactions and components appeared first in MTSthe rest of the vendor pack is well behind in shipping competing products.
It was somehow comforting to think of Microsoft in the traditional way, as nothing more than technical copycats. Today, though, not only do they have a commanding market position and all the money in the world, theyre also bringing to market some of the best new ideas. Merging components and transactions is a case in point.