Skip to main content

Taking Service-Oriented Architectures Mobile, Part 2: Mobile Transactions

August 2, 2005

{cs.r.title}








Contents
Introduction
Using Transactions on a Device
Mobile Movie Reservations
Participating in a Transaction
Summary
Resources

In this series of articles, we are looking at how it is possible to
extend the basic principles of service-oriented architecture (SOA)
to devices at the edge of the network (such as cell phones, PDAs and
set-top boxes) so that they can connect to enterprise-level
services within a network.

In " href="http://today.java.net/pub/a/today/2005/06/21/mobile1.html">Part
1: Thinking Mobile," we described how interfaces to network
services could be defined and implemented at a level of abstraction,
regardless of the mobile network or underlying network protocol
layers. This means that we can "talk" to network services directly
from any cellular phone that has a standard Java implementation
(Java ME) without any concern over whether we are using 2G, 2.5G, or
3G mobile networks, or whether the underlying network protocol is iMode,
WAP, or HTTP.

In this article, we are going to extend the facilities of our
architecture by adding the ability for devices to become involved in
atomic transactions. Transactions are vital in ensuring that all of
the relevant resources that a system provides are coordinated and
managed so that the overall state of the system remains
consistent.

The benefits of using transactions can range from the simple, such
as making sure that your seat at the movie theater is not double
booked, to the essential, such as making sure that the correct piece
of medical equipment can be provided to the correct field hospital
in a disaster zone.

Introduction

For the architecture we are designing, we need transactions to be
both href="http://en.wikipedia.org/wiki/Distributed_transaction">distributed
and mobile--which, in simple terms, means that a transaction
represents a "unit of work" between a set of cooperating services on
the network and over the air.
Under a transaction, either:

  • The unit of work is executed as a whole: For example, your airline flight reservation is confirmed and your
    credit card is debited.
  • None of the actions are completed: Your airline flight reservation is rejected because the
    flight has just been fully booked, and so your credit card account is
    not debited.

In a SOA, a transaction manager is usually a service that is used
to coordinate the other services participating in the
transaction. It does this by creating the transaction context and
then coordinating the participating services. Normally, this is
implemented using
a two-phase
commit
model in which a commit is performed on all of the
participants, or an abort is performed on all of the participants,
giving us the "all or nothing" behavior that we are looking for.

If we are going to implement services such as mobile banking or
logistics and supply chain applications, then we need to devise a
method of making our mobile devices capable of being involved in any
transaction, either explicitly by talking directly to the
transaction manager, or implicitly through calls to services that
are themselves transactional. Or, for maximum flexibility, both.

Using Transactions on a Device

Our mobile SOA has targeted the lowest common
denominator for Java on devices, namely MIDP/CDLC, which means that
any more powerful Java-enabled device can also take advantage of the
architecture. When we took at look at designing in the support for mobile
transactions, we settled on two sets of interfaces that are used
on the device to create, abort, and commit transactions, and also to
participate in transactions.

We also needed to implement code to manage leases on transactions
to set time limits on operations. This means that if parts of the
system fail, we can abort the transaction after a predetermined
amount of time. For example, if a mobile client becomes disconnected
when your train goes through a tunnel and the network connection
cannot be maintained, the transaction manager will abort the
transaction when the lease expires.

If the transaction is aborted,
all of the active participants for that transaction will be
notified. As a result your business services can release any
resources that had been "locked" for the expired transaction.
To recap: mobile clients can either be explicitly or implicitly
involved in any transaction.

Mobile Movie Reservations

For a simple example, our local movie theater has given us a brief
to design a prototype mobile seat booking application, so that
moviegoers can book a ticket to their favorite movie and reserve a
seat on the way to the theater. This type of system inherently
requires transactions to make sure that seats are not double booked,
and that should a booking fail, the customer is not charged.

On the device, we access the transaction manager in order to create
a transaction, and then use that transaction object to pass the
business services participating in the transaction.

//MIDP code -  using explicit transactions
//Obtain proxies for the Transaction Manager & the business service 

TransactionManager txnMgr= TransactionManagerFactory.getService(); 
SeatReserver seatReserver = SeatReserverFactory.getService(); 

//creating a transaction with a five minute lease
long lease= 60 * 1000 * 5;
Transaction txn=txnMgr.create(lease);

//register the transaction with the business service 
seatReserver.newTransaction(userDetails,txn); 

//user has selected the date, the movie and the seat(s)
seatReserver.reserve(dateTime, movieID, seatID ,txn); 

//when all operations are complete, prompt the user to commit the transaction  
txnMgr.commit(txn);

In the code example above, both the TransactionManager
and SeatReserver are "shadow" proxies (to remote
services) created with the mobile stub generator, which takes a
service interface as an input and generates the code required for a
mobile client to communicate with a remote service. This is
described in detail
in href="http://today.java.net/pub/a/today/2005/06/21/mobile1.html#service_oriented_architecture">part
one of this series.

Having obtained the proxies to the two services, the code then
obtains a Transaction object from
the TransactionManager with a lease of five minutes,
meaning that the client code has to complete all operations using
the transaction within that timeframe; otherwise, the transaction
manager will abort the transaction.

The transaction object is then passed to
the seatReserver along with user's details, to allow the
service to register as a participant in the transaction. More about
that later.

In this example, the SeatReserver service forms part of
the remote SOA that provides access to a billing service, which in
turn participates with the transaction created on the mobile
client.

An alternative approach would have been to encapsulate the usage of
a transaction within the business service itself and have a method
on the service to commit the transaction internally; for example, a
"purchase" method.

Participating in a Transaction

In the above example, the mobile client code is responsible for
committing or aborting the transaction. Let's now take a look at
how your business services gets notified.

The architecture we have designed provides a simple model that allows
you to connect adapters to your existing business services. This
means that you do not need to make any modifications to those
services, but just simply write the connector code--this gets
loaded at runtime by the gateway.

In our design, the transaction manager is only responsible for
managing the two-phase commit protocol, so your business service (or
connector code) needs to implement
the TransactionParticipant interface to be able
register as a participant with
the TransactionManager.

In the earlier client example, the mobile application first created
a transaction and then passed that transaction to
the SeatReserver service, by invoking the
method seatReserver.newTransaction(). Let's put all
the pieces together and take a look at how
the SeatReserver service actually interacts with the
transaction manager.

//Service code example to participate in a Transaction

public class SeatReserverImpl extends AbstractTransactionParticipant{ 

  private TransactionManager transactionManager;

  public SeatReserver(TransactionManager txnMgr){
    transactionManager=txnMgr;
  }

  public boolean prepare(Transaction txn){ 
    //return true if this participant to ready to commit 
  } 
  public void commit(Transaction txn){ 
   //code to actually commit the transaction 
  } 
  public void abort(Transaction txn){ 
   //The transaction has been aborted 
  }

  //methods invoked from mobile client
  public void newTransaction(UserDetails user,Transaction txn){   
    //once you have joined the transaction the TransactionManager will   
    //be able to invoke methods on the TransactionParticipant methods, 
    //commit, prepare and abort   

    transactionManager.join( txn, this/*TransactionParticipant*/);
  }

  public void reserve(Date dateTime,long movieID,long seatID,Transaction txn){
    //store data keyed on the transaction's ID
    //later this data is either committed to a database
    //or aborted depending on the final state of the transaction 
  } 
}
 


The diagram in Figure 1 below shows the relationships between the
  transaction manager and the SeatReserverImpl

class shown above.

Figure 1
Figure 1. Transactions UML class diagram

Looking at the UML diagram in Figure 1, you will notice that both TransactionManager and TransactionParticipant directly implement the Java RMI interface Remote, whereas the SeatReserver indirectly implements Remote by extending the AbstractTransactionParticipant. This is because the TransactionManager runs as Java RMI service as part of the overall SOA, which allows for a mixture of RMI, Jini, and user-defined connectors that can be exposed as services.

Here is a look at the whole architecture from the mobile client's perspective:

Figure 2
Figure 2. Mobile transaction architecture

In Figure 2 above, you can see that the mobile device is using a "transaction pack." This is a class library containing prebuilt stubs that can communicate with the remote transaction manager. The transaction manager is loaded as a connector service by the gateway, thus making it available (via an RMI lookup) to other business services running on the network.

Summary

Transactions are vital to ensure that all of the relevant resources that a system provides are coordinated and managed so that the overall state of the system remains consistent. A transaction represents a "unit of work" between a set of cooperating services on the network and over the air, which is either executed or aborted as a whole. Transaction participants register an interest in a transaction with a transaction manager. The transaction manager is responsible for coordinating transaction participants using the two-phase commit protocol.

In a SOA where services are inherently distributed and decoupled, client applications may need to be able to interact with multiple services, all within a single transactional unit. Leases are used to ensure that transactions can be automatically aborted if the client crashes, or fails to commit or abort the transaction. Simple transaction-based systems can be implemented completely by the remote services when these services are tightly coupled. The choice of whether the client application or a remote service creates and commits/aborts a transaction is determined by the required functionality of the system you are building. The ability to control the state of a transaction for either a mobile client or business service (or both) provides maximum flexibility.

Resources

Code examples from this article

Net Caboodle documentation

J2ME Wireless Toolkit

Eclipse plugin and mobile stub generator

Eclipse J2ME plugin

NetBeans 4.2 plugin and stub generator

NetBeans version 4.2 (dev build) and NetBeans 4.2 Mobility Pack

"NetBeans Mobility Pack Quick Start Guide"

JMX JConsole mobile demo

Nigel Warren is a co-founder of Net Caboodle and co-author, with Philip Bishop, of the books Java in Practice and JavaSpaces in Practice, both published by Addison Wesley Longman.
Robert Cooper is a J2EE developer living in Atlanta, GA.