ResearchUniversity of NewcastleReturn to Research List
Arjuna Project Distributed Systems Research Department of Computing Science, University of Newcastle Tyne, UK, NE1 7RU m.c.little@newcastle.ac.uk Providing
end-to-end transactional Web applications using the Object Transaction
Service 1. IntroductionThe Web frequently suffers from failures which can affect both the performance and consistency of applications running over it. For example, if a user purchases a cookie granting access to a newspaper site, it is important that the cookie is delivered and stored if the user’s account is debited; a failure could prevent either from occurring, and leave the system in an inconsistent state. For resources such as documents, failures may simply be annoying to users; for commercial services, they can result in loss of revenue and credibility. Atomic transactions, with their “all-or-nothing” property, are a well-known technique for guaranteeing application consistency in the presence of failures. Although Web applications exist which offer transactional guarantees to users, these guarantees only extend to resources used at Web servers, or between servers; clients (browsers) are not included, despite their role being significant in applications such as mentioned previously. Providing end-to-end transactional integrity between the browser and the application (server) is therefore important, as it will allow work involving both the browser and the server to be atomic. However, current techniques based on cgi-scripts cannot provide end-to-end guarantees [1]. As illustrated in figure 1 the user selects a URL which references a cgi-script on a Web server (message 1), which then performs the transaction and returns a response to the browser (message 2) after the transaction has completed [2]. Returning the message during the transaction is incorrect since it may not be able to commit the changes.
Figure
1: transactions through cgi-scripts In a failure free environment, this mechanism works well. However, in the presence of failures it is possible for message 2 to be lost between the server and the browser, resulting in work at the server not being atomic with respect to any browser related work. With the advent of Java it is possible to empower browsers so that they can fully participate within transactional applications. To be widely applicable any such transaction system must be standards compliant. The most widely accepted standard for distributed transactions is the Object Transaction Service (OTS) [3]. However, rather than require a browser to incorporate a full OTS implementation for all applications, we are interested in the case where it would be considered either undesirable or impractical, e.g., because of the overhead and security implications involved in incorporating the required CORBA services within a browser. In addition, we expect that the majority of an application’s resources, particularly in the area of electronic commerce, will continue to reside within protected domains. 2. End-to-end transactional guaranteesOur aim was to allow the construction of transactional applications with end-to-end guarantees without requiring (substantial) support from the browser; the level of browser support will depend upon the application, but should be minimal, e.g., simply writing a cookie to the user’s disk. Figure 2 shows a lightweight transactional bank account: apart from necessary persistence mechanisms, the transaction and concurrency control services are all managed for the browser by the server; the cookie object still participates within any transactions involving the bank, and therefore the transaction manager guarantees that its state changes are transactional.
Figure
2: lightweight transactional browser In the following sections we shall describe how we have provided this lightweight transactional mechanism using the OTS. 2.1 Browser resourcesThe OTS specification allows transactional objects to delegate their ACID responsibilities to recoverable objects (those which support the Resource interface defined in the CosTransactions module); through this technique it is possible to encapsulate non-transactional resources within OTS Resources, such that they assume the responsibility of ensuring the object is transactional. Therefore, the solution we chose to the problem of providing lightweight end-to-end transactional guarantees is through the use of Resource implementations which “wrap” the non-transactional browser. These Resources are registered with, and driven by, the transaction manager at the server, and work with the browser-side application to make it transactional. This allows the browser portion of the application to be extremely simple and lightweight. Although this browser Resource will typically be specific to the application for which it was created, the functional requirements all Resources must fulfil will be the same: · prepare: the Resource transmits to the browser application the identity of the transaction it has been registered with, which can be used to replay the transaction in the event of a failure. If the Resource passes any results back to the browser application (e.g., a cookie) it should not use them at this stage, since the transaction has not terminated. If the browser does not respond to this message, the server-side Resource may assume it has failed and cause the transaction to abort (by returning VoteRollback from prepare.) If the transaction aborts, all of the other work performed within its scope will be undone. · commit: the application is guaranteed that all of the work performed within the transaction will be made durable, despite failures. Crash recovery mechanisms can be relied upon to complete partial transactions arising due to failures. Therefore, the Resource can make any “state changes” permanent, e.g., by instructing the browser to store the cookie, or display/decrypt the purchased document. If the Resource does not reply to the commit request then the transaction manager will assume it has crashed and crash recovery will complete the transaction. · rollback: the Resource transmits the reason for the rollback to the browser, e.g., insufficient funds within the user’s account. This technique provides a lightweight means for Web applications to gain end-to-end transactional integrity. The transaction coordinator, and the majority of the transaction infrastructure, reside within the server, while the browser application remains relatively simple, needing only to be able to make any “changes” permanent in the case of a commit, or to undo them if the action aborts. 3. Overview of an OTS implementationWe have designed and implemented OTSArjuna, a C++ transaction toolkit which complies with the OTS specification (including supporting subtransactions), and which provides programmers with the ability to implement Web applications with end-to-end transactional guarantees [4]. This OTS implementation is extremely portable, and runs on over 7 different ORBs. However, in the on-line example to be described later we have used Orbix 2.2MT from Iona. Rather than require programmers to make use of the low-level OTS, concurrency control and persistence APIs, OTSArjuna provides a high-level API for building transactional applications and frameworks [5]. This API automates the activities concerned with participating within an OTS transaction, such as creating and registering appropriate Resource implementations, propagating locks etc. The architecture of the system is shown in figure 3.
Figure
3: OTSArjuna structure The OTSArjuna model for building transactional applications exploits object-oriented techniques to present programmers with a toolkit of classes from which application classes can inherit to obtain desired properties, such as persistence and concurrency control. Each class is concerned with a single functionality, and these classes form a hierarchy, part of which is shown in figure 4. By inheriting from LockManager, user classes are automatically transactional, with LockManager and StateManager being responsible for guaranteeing the ACID properties (isolation and durability respecitvely). Apart from specifying the scopes of transactions, and setting appropriate locks within objects, the application programmer does not have any other responsibilities: the system guarantees that appropriate Resource objects are registered with transactions, and that in the event of failures crash recovery mechanisms are invoked automatically.
Figure
4: OTSArjuna class hierarchy 4. Bank cashpoint exampleTo illustrate the technique of incorporating browsers into transactions, we have implemented a bank account example, which is available on-line (http://arjuna.ncl.ac.uk/). Consider the case of an on-line bank which allows users to inspect, remove, and insert money from their accounts; the bank runs on an ORB which resides on a Web server. When money is removed it is converted into digital cash tokens which are stored and manipulated by the browser, and contain the token’s current “cash” balance; we shall assume that these tokens can be presented to other Web-commerce applications as payment for services. Insertion of money to an account is simply the reverse, whereby a token is consumed, and the user’s account is credited by the amount left within the token. The bank requires to make the delivery of the cash token to the user’s browser and the debiting of the user’s account atomic. Failures must not result in inconsistencies at the browser or the bank. Figure 5 shows the browser portion of the application, consisting of a Java applet which displays a graphical representation of the bank; user accounts are accessed via a PIN. To guarantee consistency in the presence of failures, each operation is performed within the scope of a transaction; the transaction manager runs at the bank’s Web server. Although the operation to inspect an account is transactional, it only reads the state of the account and therefore there is no actual requirement for end-to-end transactional integrity: if a failure occurs, the user can simply re-issue the request. However, both withdrawing and inserting money require stronger transactional guarantees: each operation must atomically modify the account and either deposit or consume a digital cash token to/from the browser. During the prepare phase of each transaction the applet will display the unique transaction identifier for the operation. During the commit phase, the bank server will return the digital cash token to the browser and the applet can then use this to animate (e.g., money appears to be dispensed). In a real system the token would need to be stored by the browser. If the transaction aborts, an error message will be displayed giving the reason, e.g., insufficient funds.
Figure
5: Bank applet. 4.1 Server application classesTo enable the bank to service multiple clients concurrently, each account is a separate transactional object, responsible for its own persistence and concurrency control. Therefore, concurrent modifications to different bank accounts will not interfere. Using OTSArjuna, each bank account is an instance of the Account class, which is derived from LockManager: enum Outcome { DONE, NOTDONE, INSUFFICIENT_FUNDS, ACCOUNT_ERROR, LOCKED };
class Account : public LockManager void insert (int amount); private: We shall first
show the implementation of the withdraw
method without browser participation. We will then describe the necessary
browser Resource for end-to-end
transactional guarantees, and return to the withdraw
operation to show how it requires modification in order to incorporate
this Resource.
The withdraw
method first starts a new transaction and then attempts to obtain a lock
on the account object (by calling the setlock method
of the LockManager class). Because the
withdraw
operation will modify the state of the account, it tries to obtain an
exclusive (write) lock. If the operation is performed successfully (e.g.,
there is sufficient funds in the account), the transaction is committed,
otherwise it is rolled back. (Note: for simplicity the code fragments
shown do not perform all necessary error checking.) void
Account::withdraw (int money) In order to involve the browser such that it can receive the cookie when the user’s account is finally debited, we need to create an instance of a specific Resource which will encapsulate the browser for the duration of the transaction. The signature of the BrowserResource is shown below. class BrowserResource
: public CosTransactions::ResourceBOAImpl CosTransactions::Vote prepare
(); private: When created,
each BrowserResource
is given the identity of the transaction it has been registered with, so
that it can transmit it to the browser during the prepare phase; this can
be used in the event of a failure. The Resource
also receives the outcome of the operation and the cash token to send back
to the browser. The browser applet is represented to the resource by an
instance of the Browser class;
this is simply a traditional client proxy for a corresponding object
within the browser. To make the
browser transactional, the BrowserResource must keep a
durable record of its progress; this may then be used by crash recovery in
the event of a failure. For example, consider the implementation of the prepare
method: CosTransactions::Vote
BrowserResource::prepare () Before the BrowserResource sends the transaction’s identity it calls saveState which will permanent sufficient information to allow its role in the transaction to be replayed in the event of a failure. If saveState fails, the transaction must abort. If the subsequent invocation on the browser proxy fails, the resource assumes that the browser has failed, removes any state it previously saved, and forces the transaction to rollback. If no errors occur during prepare, the resource informs the transaction coordinator that it is ready to commit. During the commit phase, the Resource sends the token to the browser and awaits an acknowledgement. If no acknowledgement is received, the Resource relies upon crash recovery mechanisms to complete its work. void BrowserResource::commit () In the event of a
rollback the resource will send an error message to the browser indicating
the reason for the failure. void
BrowserResource::rollback () If a failure occurs during the transaction, the user can re-issue the request by supplying the transaction identifier. The crash recovery mechanisms at the server will determine the transaction outcome and complete the work. If no record of the transaction can be found it can be assumed that the transaction aborted. Having considered
the implementation of the BrowserResource, we can return to the withdraw
operation. We wish to incorporate the browser within the transaction before
it terminates, such that the browser will be informed of the outcome
regardless of whether the transaction subsequently commits or rolls back.
Therefore, after performing withdrawal we obtain a reference to the
current transaction’s Coordinator,
and register a new instance of the BrowserResource
with it. The transaction then either commits or aborts, depending upon
whether the withdrawal was successful, and drives the BrowserResource
to either deliver a token or an error message, respectively. If a failure
occurs, the user’s account will not be debited and
neither will the browser obtain a cash token. void
Account::withdraw (int money) coord->register_resource(res);
if (result == DONE) Acknowledgements The work reported here has been supported in part by a grant from UK Engineering and Physical Sciences Research Council (grant no. GR/L 73708). References [1] T. Sanfilippo and D. Weisman, “Applications of the Secure Web Technology in Transaction Processing Systems”, The Open Group Research Institute, November 1996. [2]
“Transarc DE-Light Web Client Technical Description”, Transarc
Corporation, February 1996. [3] “CORBAservices: Common Object Services Specification”, OMG Document Number 95-3-31, March 1995. [4] M. C. Little and S. K. Shrivastava, “Java Transactions for the Internet”, Proceedings of the 4th Usenix Conference on Object-Oriented Technologies and Systems, Santa Fe, New Mexico, April 1998. [5] M. C. Little and S. K. Shrivastava, “Distributed Transactions in Java”, Proceedings of the 7th International Workshop on High Performance Transaction Systems, September 1997, pp. 151-155.
|