The Artima Developer Community
Sponsored Link

Survival of the Fittest Jini Services, Part II
Use Transactions to Coordinate the Reliable Interaction of Jini Services
by Frank Sommers
First Published in JavaWorld, July 2001

<<  Page 5 of 8  >>

Advertisement

Transaction Lifecycles

Once all the bookstore services are transactional, you can at last order your favorite book. The transaction client is the Jini service that initiates the transaction. The client might or might not also be a participant in the transaction. Since printing or displaying the PurchaseConfirmation is part of the book purchase transaction, we will make the BookStore service both a client and a participant.

The client follows these steps to initiate a new transaction:

  1. It discovers the transaction manager service. Since it's just a regular Jini service, you can follow the normal Jini service discovery mechanism.
  2. Since different objects could represent various transaction semantics, you create a Transaction via a factory class. Like many Jini entities, a transaction is a leased resource. Calling TransactionFactory's create() method produces a ServerTransaction.Created object, which bundles a new transaction with its lease.
  3. If the client is also a transaction participant, it can at this point join the transaction.
  4. It then passes the transaction object as a parameter in method calls to other services.

A new transaction starts out in the active stage. In this stage, the services perform their work under the transaction. For instance, the credit card service charges your account, the bookstore service locates and queries the shipping services, and a package delivery is scheduled. Finally, the bookstore service must produce a purchase confirmation. During these activities, all three services must be ready to roll back any changes they make, since the whole transaction's success is not yet guaranteed.

At some point, the client (or any other participant, for that matter) indicates that the transaction must complete. With our bookstore, this might occur right after we've displayed or printed the order confirmation, or after we've waited a set amount of time for the services to finish their work. Then the 2PC protocol drives the transaction to completion.

The transaction manager coordinates the transaction's commitment. The client (or any other participant) calls the commit() or abort() methods on the Transaction object. This in turn causes the manager to call the prepare() methods on each participant.

At this point, the transaction enters the voting stage. Each participant must vote: Is it prepared to roll forward the transaction's changes, does it need to abort the transaction, or does it not care either way (because the transaction caused no changes in its state)? The participants' possible votes are PREPARED, ABORT, or NOTCHANGED. Most significant, if any participant cannot ensure its transactional guarantees, it must indicate that fact. For example, the credit card service might not be able to save the new credit card balance.

When a participant votes PREPARED, it says, in effect, that I am now committed to the changes made under the transaction. This implies that, given the order to roll forward, the participant guarantees to commit the changes -- it cannot fail. Among other things, this means that the changes have already been saved in persistent store (to guarantee the transaction's durability property).

When, and only when, all participants vote either PREPARED or NOTCHANGED, the coordinator calls the commit() method on each participant. When all participants commit their changes, the transaction is in the COMMITTED state and can thereafter be forgotten. (Transactions typically don't persist after they've completed, although the spheres of control notion I mentioned in the first part of this series assumes that they do, which opens up many interesting possibilities.)

The commit() call instructs a participant to finish the transaction, which means that the participant no longer needs to enforce the transaction guarantees. The results of the changes made during the transaction now become visible to objects outside the transaction, locks held by the transaction are released, and so forth. The commit() method doesn't have a return value, since a PREPARED vote previously implied a guaranteed successful commit.

If any participant votes ABORT, the transaction manager calls the abort() method on all participants, instructing them to roll back all changes made during the transaction and release any resources they've reserved.

In this sense, the transaction provides a set of computation guarantees: if any participant decides that it cannot, for some reason, abide by the transaction's semantics, the entire computation will be cancelled rather than produce an unreliable result and unpredictable side effects.

Figure 3 shows the transaction's different states during the 2PC protocol from the transaction client's point of view:


Figure 3. The client's view of a transaction

Figure 4 illustrates the interaction between a participant and a transaction:


Figure 4. The participant's view of a transaction

Finally, Figure 5 illustrates how a manager drives the transaction to completion:


Figure 5. The manager's view of a transaction

<<  Page 5 of 8  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2017 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us