White Paper
July 1998
For more information, press only:
Bill Schneider
Waggener Edstrom
(503) 245-0905
bills@wagged.com
Microsoft® Transaction Server (MTS) is the transaction service in the Microsoft® Windows NT® operating system. First available in 1996, Microsoft Transaction Server technology is now in use at many organizations. Enterprise JavaBeans is a specification for a Java-based transaction service. Created by a group of companies led by Sun Microsystems Inc., the initial specification for Enterprise JavaBeans was released in spring 1998. Both Microsoft Transaction Server and Enterprise JavaBeans target the creation of component-based, transaction-oriented applications. This paper provides a comparison of these two technologies. More specifically, the paper analyzes the similarities and differences between the ways the two component models handle types of objects, transactions support, managing state, controlling complexity, portability, interoperability, language choice and administration.
Put simply, a transaction can be thought of as a set of events that are committed or rolled back as a unit — either all the events happen, or none of them do. For example, transferring $100 from your savings account to your checking account requires both subtracting the money from your savings account and adding it to your checking account. To achieve a consistent result, either both operations should occur or neither one should. Transaction-oriented applications like this are very common; therefore, many vendors provide software that makes writing transactional applications easier. And because transactional applications often need to handle hundreds or thousands of clients (that is, users at workstations), services that make it easier to build scalable applications are commonly built into products that support transactions.
Both Microsoft Transaction Server and Enterprise JavaBeans support transactional applications and provide services for scalability. Because the two technologies attempt to solve many of the same problems, they have much in common. The easiest way to illustrate their similarities is to describe the basic architecture and terminology of each.
MTS is based on the Component Object Model (COM), and a MTS application is implemented as one or more components. As shown in Figure 1, these components are managed by the MTS Executive. COM objects that run under the control of MTS are called Microsoft Transaction Server objects. As is usually the case with COM, MTS relies on a class factory object to create specific instances of each COM class. To allow MTS to provide extra services, the Microsoft Transaction Server Executive transparently inserts a wrapper object between each object it manages and that object's client. For example, when a client uses the COM IClassFactory interface to create an instance of a MTS object, that call is actually made on a factory wrapper object implemented by MTS, which in turn passes on the call to the real class factory. Similarly, every method call a client makes on the business methods of a MTS object is first handled by a Microsoft Transaction Server-supplied context wrapper object. The Microsoft Transaction Server Executive also supplies a context object for each MTS object. This context object maintains information specific to the MTS object, such as what transaction it belongs to (if any) and whether it has completed its work. Every context object implements the IObjectContext interface, through which a MTS object can access the services that MTS provides.
The general architecture of Enterprise JavaBeans is very similar to MTS; little more than the terminology is changed. As shown in Figure 2, an Enterprise JavaBeans container acts like the Microsoft Transaction Server Executive, hosting enterprise beans rather than MTS objects. Each bean exposes its own Home interface, analogous to the COM IclassFactory interface, allowing a client to create instances of specific classes. And, like MTS, the Enterprise JavaBeans container provides a wrapper for each bean it manages. An Enterprise JavaBeans Home object wraps the bean's Home interface, while an Enterprise JavaBeans Object wraps the bean's business methods. Also, an Enterprise JavaBeans container provides either the javax.ejb.SessionContext interface or javax.ejb.EntityContext interface, both of which offer services similar to Microsoft Transaction Server's IObjectContext. And although it's not shown in the diagram, an enterprise bean is required to implement one or more additional interfaces that the Enterprise JavaBeans container uses to interact with the bean.
Both MTS and Enterprise JavaBeans rely on a transaction coordinator, a logically separate service responsible for ensuring that all operations in a transaction are successful or that none of them are. In MTS, this function is implemented by the Distributed Transaction Coordinator (DTC), a service included in Windows NT. The Microsoft Transaction Server Executive communicates with the DTC through OLE Transactions, a COM-based interface. The Enterprise JavaBeans specification does not define how a transaction coordinator is implemented or how an Enterprise JavaBeans container communicates with the transaction coordinator. Instead, each vendor is allowed to implement these functions in any way it wishes.
MTS objects are typically designed to encapsulate some set of business functionality. For example, a MTS object might allow a client to transfer money between two accounts or build and submit an order of some kind. Because MTS objects are written as distinct components, business functions encapsulated into these objects can be combined in arbitrary ways, allowing them to be reused flexibly. Although it's not strictly required, a MTS object is typically accessed by one client at a time, and it may (but isn't required to) use transactions.
The Enterprise JavaBeans specification takes a more complex view of objects. Unlike MTS, Enterprise JavaBeans explicitly defines two different types of enterprise beans. The first, called session beans, are much like MTS objects. Session beans encapsulate some segment of business logic, are typically accessed by one client at a time, and optionally use transactions. The Enterprise JavaBeans specification also defines a type of persistent object called an entity bean. Unlike session beans, entity beans represent a specific set of persistent data stored in a database, such as an employee record or a particular order. Each entity bean has a unique key that identifies it, and each one is intended to be accessible by many clients simultaneously. Furthermore, entity beans are required to use transactions.
Building MTS as an extension of COM has other benefits as well. For example, a MTS client need do nothing special to create and work with transactional objects; to a client, a MTS object looks like an ordinary COM object. An Enterprise JavaBeans client, on the other hand, must understand and correctly use new interfaces and methods to create, manage and destroy enterprise beans. Because MTS is built on COM, it automatically benefits from the richness and maturity of the COM environment. Enterprise JavaBeans, by contrast, is forced to invent much of its own infrastructure, including such basics as persistent object support and interfaces, allowing clients to create remote beans.
A transaction defines a set of events that are guaranteed to be committed or rolled back as a unit. Accordingly, every transaction has a beginning, some number of events that are part of the transaction (such as database updates), and an end. Exactly how a transaction's boundaries are demarcated can vary. A common approach in traditional client/server transaction products is to require the client to make a specific call to the transaction coordinator to begin the transaction. The client then makes calls to the components that carry out this transaction's work. The transaction is completed with another explicit call to the transaction coordinator. This final, transaction-ending call can indicate that the transaction should be committed, making all its changes permanent, or aborted, causing all its changes to be rolled back. It's the job of the transaction processing system to ensure that exactly one of these two outcomes occurs.
When combining transactions with components, the traditional client-controlled model isn't usually the best approach. With MTS services, Microsoft introduced a new way to demarcate transaction boundaries, called automatic transactions, which allows clients to remain unaware of when transactions begin and end - clients never need to make explicit calls to begin or end a transaction. Instead, the beginning of a transaction depends on the value of that component's transaction attribute. This value can be set to one of four possibilities:
When it has finished its work, a MTS object can call either SetComplete, if it wishes to commit that work, or SetAbort, if the work it has done should be rolled back. If neither is called by the time this object's transaction ends, the Microsoft Transaction Server Executive behaves as though the object called SetComplete (the default behavior is to commit the transaction). These calls are made by a method in the MTS object itself, not by the client (again, the client need not be aware that transactions are being used). If every object participating in the transaction agrees to commit, the Microsoft Transaction Server Executive will tell the transaction coordinator to commit the transaction. If any MTS object in this transaction calls SetAbort, however, the Microsoft Transaction Server Executive will tell the transaction coordinator to abort the transaction.
The Enterprise JavaBeans specification defines three approaches to demarcating transaction boundaries:
Given that its creators are trying to ensure that Enterprise JavaBeans can be retrofitted onto existing legacy products, they have chosen to support the traditional client-managed approach to transaction demarcation. Enterprise JavaBeans has also adopted MTS's innovation of automatic transactions. In fact, Enterprise JavaBeans's container-managed transactions are nearly an exact clone of MTS's automatic transactions. An enterprise bean can be labeled as TX_REQUIRES_NEW, TX_REQUIRED, TX_SUPPORTS or TX_NOT_SUPPORTED, all of which have the same meaning as in MTS. And similar to MTS, Enterprise JavaBeans assumes that a bean wishes to commit the transaction unless it explicitly invokes the setRollbackOnly method. Enterprise JavaBeans does not provide an analog to the MTS SetComplete call, however.
At first glance, Enterprise JavaBeans' many choices can appear attractively flexible. But they are also very complex. What happens, for instance, when different approaches to transaction demarcation are used simultaneously? Suppose an application begins a client-managed transaction, then executes a method in an enterprise bean that's configured to require a new container-managed transaction. And suppose this bean creates yet another bean that's using bean-managed transactions. What happens when the client commits its transaction? Understanding all the possible combinations (legal and illegal) and their outcomes will be very challenging for developers. And if developers can't easily understand the outcome of their transactions, it will be difficult for them to write correct applications? Compared to the simple, unified model that MTS provides, Enterprise JavaBeans offers developers a confusing and potentially error-prone array of choices for controlling transaction boundaries.
MTS provides all three transaction demarcation options found in Enterprise JavaBeans, but in a less confusing way. As previously described, Enterprise JavaBeans container-managed transactions are virtually identical to MTS automatic transactions. MTS also supports client-managed transactions, allowing a client to determine explicitly when a transaction should begin and end. But unlike Enterprise JavaBeans, MTS builds this service on top of automatic transactions rather than introducing an entirely separate mechanism. This eliminates the possibility of confusion between automatic transactions and client-managed transactions. And, finally, a MTS object with its transaction attribute set to Not Supported can make direct calls on the DTC using OLE Transactions. By doing this, a MTS object can demarcate transactions on its own, just like an Enterprise JavaBeans bean-managed transaction.
A typical transactional application accepts input from a client, such as a user at a workstation, then makes changes to one or more databases based on this input. If the transaction commits, the database changes are made permanent. If it aborts, those changes are rolled back. Ensuring the consistency of the databases' state in this kind of application is a primary goal of a transaction processing system.
But what about the state of the application itself? The objects that make up this application may retain information in memory during the transaction. For example, an object that transfers money between two bank accounts may keep the balance of both accounts in memory while the transaction is in progress. If the transaction commits, this in-memory state will match what is in the database. If the transaction aborts, however, this state will be wrong, because neither MTS nor Enterprise JavaBeans will roll back the state of in-memory objects. This potential for hanging on to incorrect data poses a problem for application developers: How can they ensure that their in-memory state is in sync with what's in the database after a transaction has ended? Without some way to achieve this, the application might rely on this incorrect in-memory information to handle the next request, leading to invalid results.
MTS's solution to this problem is simple and direct: When an object calls either SetComplete or SetAbort, indicating that it has completed its work, MTS deactivates that object. Although clients still retain their references to those objects, MTS silently re-creates another instance the next time the client calls a method, a process called just-in-time activation. No MTS object that is participating in a transaction is allowed to maintain any in-memory state across a transaction boundary. Instead, any state that object had is destroyed by the time the transaction ends and so must be refreshed from a reliable source (for example, the database) when it is next needed. This completely eliminates the possibility of retaining incorrect state that could inadvertently get used in the next transaction. In Enterprise JavaBeans, however, this possibility is quite real. An enterprise bean isn't deactivated when a transaction ends, which means that Enterprise JavaBeans developers face the problem of ensuring that the bean's state matches what's on a disk.
The Enterprise JavaBeans specification places greater burden on the developer, stating that an enterprise bean "must refresh any potentially stale database data it contains at the beginning of the next transaction." This isn't a problem in MTS, since the end of a transaction also marks the end of any state maintained by a MTS object. The result is that it is easier to write correct applications with MTS, since there is no risk of maintaining old, stale data in a MTS object between transactions.
Another benefit of destroying an object's state at the end of each transaction is that it forces the object to release any shared resources it is holding. This greatly improves application scalability, since those resources are now free to be used by another object. Perhaps the best example of a limited shared resource is an open connection to a database. One of the primary reasons that three-tiered distributed applications, such as those built using MTS, can scale better than two-tiered applications is that they can share these database connections. Rather than requiring one for each client, for example, MTS allows a group of open database connections to be stored in a pool and handed out as needed. When a MTS object has finished its work, the object is deactivated and the database connection is returned to the pool for use by another object. This sharing of database connections in MTS is accomplished by the ODBC resource manager, which transparently maintains a pool of open connections. Because each MTS object is forced to give up its connection by the end of each transaction, a single object can't hoard this scarce resource.
Enterprise JavaBeans, however, does not deactivate an enterprise bean at the end of each transaction and so doesn't require the bean to give up its database connections. Enterprise JavaBeans doesn't define any specific mechanism for pooling and reusing database connections. An Enterprise JavaBeans application deployed on Windows NT can use the ODBC resource manager to pool connections just as a MTS application would because this service isn't specifically tied to MTS. But what about Enterprise JavaBeans applications deployed on other systems? Unless those systems have some way to efficiently share database connections, one of the primary benefits of a three-tiered architecture is lost. The Enterprise JavaBeans specification is silent about how this should be done.
A primary goal of any transaction processing platform should be to control the complexity inherent in writing transactional applications. Understanding difficult business problems, then creating the correct code to solve them is hard enough without the need to spend time wrestling with a complex environment. Enterprise JavaBeans has difficulty meeting the goal of simplicity. Instead, Enterprise JavaBeans looks like a combination of everyone's ideas about how to accomplish transaction processing.
For example, as previously described, Enterprise JavaBeans transaction demarcation is very complex, with three different options spelled out in the specification and a myriad of possible ways to combine those options. Enterprise JavaBeans also defines two types of enterprise beans: session beans, representing business logic, and entity beans, intended to represent persistent data stored in a database. These two bean types must be treated quite differently by developers. Support for entity beans is not required by the current version of the Enterprise JavaBeans specification, so an Enterprise JavaBeans-compliant vendor can implement only session beans if desired. This adds another variable to Enterprise JavaBeans' already-complex set of options. A session bean, for example, must be configured to be either stateful or stateless, depending on the choices its creator makes. Entity beans can have either bean-managed persistence, with the bean itself responsible for issuing database calls to load and save its persistent data, or container-managed persistence, where the Enterprise JavaBeans container does this on the bean's behalf. And entity beans can be labeled as either re-entrant or nonre-entrant, depending on whether the developer has made provisions for bean re-entrancy. Furthermore, because entity beans are designed to be accessible to many clients at once, there must be some way to control concurrent access to their data. The Enterprise JavaBeans specification gives two illustrative examples of how this might be done but leaves the door open for any other approach.
Furthermore, both session and entity beans can be accessed with either Java's native Remote Method Invocation (RMI) protocol or through the Internet Inter-ORB Protocol (IIOP) defined by the Object Management Group (OMG). The OMG has also discussed the possibility of combining these two, which could eventually add yet a third protocol option. The truth is that even a casual reading of the Enterprise JavaBeans specification makes clear that this is a technology created by committee. The authors of Enterprise JavaBeans suffer from the difficulty of pleasing a diverse group of vendors, many of whom plan to retrofit existing transaction products to support this new technology. Accordingly, Enterprise JavaBeans attempts to support products that are both component-based and not component-based, database-oriented and not database-oriented, and more. This results in significant complexity and a diffuse approach to the problem.
Compare this complexity with the approach taken by MTS technology. MTS defines one style of component - a COM object - and one powerful but simple model for defining transaction boundaries. MTS components need not be configured as stateful or stateless, and they're always accessed in the same way: through COM calls. Remote clients that speak Distributed COM (DCOM) can directly invoke methods in MTS objects on other machines. For access from Internet-enabled clients via HTTP, the Microsoft Transaction Server Executive is loaded into Internet Information Server (IIS), the Web server built into Windows NT. An IIS application can then make COM calls into the same MTS objects. The creators of MTS understood the importance of simplicity, and its easy-to-understand programming model is one of MTS's most attractive characteristics.
Portability of enterprise beans across implementations from different vendors is frequently cited as a primary goal of Enterprise JavaBeans. As stated in the Enterprise JavaBeans specification, "An enterprise bean can be developed once and then deployed on multiple platforms without recompilation or source code modification." Yet the specification also states that "specialized containers can provide additional services beyond those defined by the Enterprise JavaBeans specification. An enterprise bean that depends on such a service must be deployed only in a container that supports the service." In practice, this is all but certain to lead to significant differences among products supporting Enterprise JavaBeans, which brings into question its validity as a standard.
This approach to standardization is reminiscent of the OMG's Common Object Request Broker Architecture (CORBA), where vendors introduced significant differences in their products to gain proprietary advantage. Even though the Enterprise JavaBeans specification repeats the familiar claim that enterprise beans will be "Write Once, Run Anywhere," this cannot be true in a world of specialized, proprietary Enterprise JavaBeans containers. While the specification does define a common core that every product must support, the history of ensuring portability based on nothing but paper specifications isn't encouraging (CORBA is only the most recent failed attempt at achieving this). The bottom line is that true portability of enterprise beans is likely to be elusive.
An important aspect of an effective distributed environment is seamless, secure communication among machines. MTS accomplishes this by defining one way to access MTS objects - COM calls - and specifying standard solutions for security and directory protocols. It is less clear how this will be accomplished with Enterprise JavaBeans.
As already noted, the Enterprise JavaBeans specification allows either the native RMI protocol or IIOP to be used for communication, with perhaps a third choice on the way. RMIs native protocol, now known as Java Remote Method Protocol (JRMP), is a very simple technology. It makes no provision, for example, for carrying a client's identity to the server, nor does it define a standard way to convey information about any transaction that might be in progress. The result is that even though RMIs JRMP appears to be a core protocol for Enterprise JavaBeans, this protocol cannot reasonably be used for interoperability among different vendors. Instead, using JRMP for communication from a client to an Enterprise JavaBeans server, or from one Enterprise JavaBeans server to another, requires either going without fundamental Enterprise JavaBeans functions, such as security and distributed transaction support, or adding proprietary extensions.
For multivendor communication, the Enterprise JavaBeans specification assumes that IIOP will be used. Yet using IIOP to access enterprise beans raises several questions. First, there are well-known technical issues still outstanding with this protocol, such as how servers learn of client's untimely deaths. Equally important, the creators of Enterprise JavaBeans seem to place a great deal of faith in IIOP, stating in the Enterprise JavaBeans specification that Enterprise JavaBeans's CORBA mapping "enables on-the-wire interoperability among multiple vendors' implementations of an Enterprise JavaBeans server." Given that products implementing CORBA's Object Transaction Service (OTS) over IIOP don't interoperate today even among themselves, it is difficult to understand how they will interoperate with a completely foreign technology such as Enterprise JavaBeans? And the Enterprise JavaBeans specification doesn't require using the CORBA OTS to communicate with a transaction coordinator. This means that even if IIOP interoperates flawlessly among different vendors' products, Enterprise JavaBeans-compliant products may still not work together because they use incompatible transaction coordinators. Promises of interoperability are easy to make as long as there are no actual Enterprise JavaBeans products. Once there is shipping code, however, customers are likely to find themselves with less than what they've been promised.
In fact, Enterprise JavaBeans' attempt to merge the Java environment with CORBA is inherently problematic. The Enterprise JavaBeans specification is owned by Sun, a company that has largely exited the CORBA business. Many of the Enterprise JavaBeans partners have not, however. The perceived need to merge the Java world with CORBA stems as much from the political needs of the vendors involved as from real user requirements. And, as was true with CORBA, the creators of Enterprise JavaBeans clearly want to allow differentiation among their "standard" products. Enterprise JavaBeans vendors appear to want to have it both ways: They wish to say they have a standard but still retain substantial proprietary elements in their products.
Furthermore, JRMP and IIOP provide only basic communication services and are not suited for this type of functionality. What about protocols for distributed security and directory services? Both the Java and CORBA camps define interfaces for these services, but interfaces alone are not sufficient to ensure interoperability; well-defined wire protocols are required. But agreements on what security and directory protocols should be used with Enterprise JavaBeans (or with CORBA) have yet to appear. Contrast this with MTS: By using standard protocols in a consistent way, MTS makes it easy to build an effective distributed environment, one that's capable of supporting the kinds of mission-critical uses targeted by transaction-oriented applications.
Writing specifications is a useful exercise, but they are not put to the test until implementation. To define a standard and write and publicize the specification but only then build it and see if it works is not a good idea, as has been shown by many failed standardization efforts. In fact, today's most successful standardization organization, the Internet Engineering Task Force (IETF), requires working implementations before finalizing a standard.
Yet it is doubtful that anybody actually built a complete implementation of Enterprise JavaBeans before the final specification was released. When this specification actually is implemented, the first Enterprise JavaBeans developers will probably find things that don't work or can't be effectively mapped to existing products. The result will be either changes to or more loosening of the specification.
And as might be expected from a specification-only technology, Enterprise JavaBeans doesn't define every detail. It's hard to imagine that multiple vendors can build interoperable implementations or that third parties can create a market for truly portable components with only the Enterprise JavaBeans specification to guide them. Time after time, paper-only standards have proved to be an ineffective means of achieving interoperability and portability. Without a reference implementation, there's just too much room for ambiguity.
MTS, by contrast, is a mature product, available since late 1996 and currently in use at hundreds of customer sites. And because MTS is an actual implementation rather than just a specification, its behavior is by definition unambiguous. Shipping software is much more effective than shipping specifications.
Choosing a programming language is one of the most important decisions made on any project. Striking the right balance between power, ease of use and long-term support is critical. Because no one language can meet every need, MTS allows building applications in any language that supports COM. This list includes the Microsoft® Visual Basic® development system, C++, Java and COBOL.
By design, however, Enterprise JavaBeans allows development only in Java. To the Java proponents at many vendors, most of whom have roots in C++, Java seems simple. And compared to C++, Java is simple. But the users of transaction processing software are primarily business developers, very few of whom know C++. Instead, their experience is likely to be in COBOL or Visual Basic, languages that are much more common among end users.
Both COBOL and Visual Basic can be used to write MTS applications, but neither can be used with Enterprise JavaBeans. If an organization does wish to use Java, MTS has excellent support for developing Java components. Yet Java is probably too complex for many business developers and, in any case, the entire industry will never settle on a single programming choice. By tying its fate exclusively to one language, Enterprise JavaBeans greatly limits its usefulness. And by making that language Java, Enterprise JavaBeans leaves behind a substantial percentage of its target developer market.
A component-based transaction system relies heavily on its administrator. For example, both MTS automatic transactions and Enterprise JavaBeans container-managed transactions allow setting a component's transaction requirements administratively. Both technologies also allow a component's security requirements to be set by an administrator. Other important functions, such as how in-doubt transactions should be resolved, must be performed administratively as well.
MTS provides standard graphical tools that allow an administrator to perform these types of functions. But while the Enterprise JavaBeans specification acknowledges the importance of the administrator's role, it does not explain how that role should be carried out. Without standards for administration, every Enterprise JavaBeans product will be different. Setting a component's transaction or security requirements, for example, is likely to require entirely different processes in different vendors' products. In practice, these kinds of differences will make it difficult for an organization to install and effectively use Enterprise JavaBeans containers from different companies. As is true in the CORBA world today, customers will be strongly motivated to choose and stick with a single vendor. To a very large degree, this will obviate the motivation for defining a multivendor standard in the first place. Instead, users who obtain a "standard" Enterprise JavaBeans product will find that changing to another vendor's Enterprise JavaBeans implementation is too painful to contemplate - there's just too much effort required.
The Enterprise JavaBeans specification attempts to define a platform for building transaction-oriented applications. The reality, however, is that this technology is rife with problems. The most significant are as follows:
MTS services suffer from none of these problems. Its simple programming model makes it easy to create components in any popular language, and those components will work in any MTS environment. MTS is also much more mature, a critical attribute when choosing a foundation for mission-critical transactional applications. And, most important, MTS is available today as a part of Windows NT. Given all these advantages, it is clear that Microsoft Transaction Server is the right choice for building enterprise applications.
##########
Microsoft, Windows NT and Visual Basic are either registered trademarks or trademarks of Microsoft Corp. in the United States and/or other countries.
Other product and company names herein may be trademarks of their respective owners.
The information contained in this document represents the current view of Microsoft Corp. on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.
This document is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS DOCUMENT.