JTA Global Transactions with GemFire
JTA Global Transactions with GemFire
Use JTA global transactions to coordinate GemFire cache transactions and JDBC transactions.
- The Java application, responsible for starting the global transaction
- The JTA transaction manager, responsible for opening, committing, and rolling back transactions
- The transaction resource managers, including the GemFire cache transaction manager and the JDBC resource manager, responsible for managing operations in the cache and database respectively
Using JTA, your application controls all transactions in the same standard way, whether the transactions act on the GemFire cache, a JDBC resource, or both together. When a JTA global transaction is done, the GemFire transaction and the database transaction are both complete.
- Coordinate with an external JTA transaction manager in a container (such as WebLogic or JBoss)
- Set GemFire as the “last resource” while using a container (such as WebLogic or JBoss) as the JTA transaction manager
- Have GemFire act as the JTA transaction manager
An application creates a global transaction by using javax.transaction.UserTransaction bound to the JNDI context java:/UserTransaction to start and terminate transactions. During the transaction, cache operations are done through GemFire as usual as described in GemFire Cache Transactions.
Coordinating with External JTA Transactions Managers
GemFire can work with the JTA transaction managers of several containers like JBoss, WebLogic, GlassFish, and so on.
At startup GemFire looks for a TransactionManager (javax.transaction.TransactionManager) that has been bound to its JNDI context. When GemFire finds such an external transaction manager, all GemFire region operations (such as get and put) will participate in global transactions hosted by this external JTA transaction manager.
This figure shows the high-level operation of a JTA global transaction whose resources include a GemFire cache and a database.
- Each region operation looks up for presence of a global transaction. If one is detected, then a GemFire transaction is started automatically, and we register a javax.transaction.Synchronization callback with the external JTA transaction manager.
- At transaction commit, GemFire gets a beforeCommit() callback from the external JTA transaction manager. GemFire does all locking and conflict detection at this time. If this fails, an exception is thrown back to JTA transaction manager, which then aborts the transaction.
- After a successful beforeCommit() callback, JTA transaction manager asks other data sources to commit their transaction.
- GemFire then gets a afterCommit() callback in which changes are applied to the cache and distributed to other members.
You can disable JTA in any region that should not participate in JTA transactions. See Turning Off JTA Transactions.
How to Run a JTA Transaction Coordinated by an External Transaction Manager
Use the following procedure to run a GemFire global JTA transaction coordinated by an external JTA transaction manager.
- Configure the external data sources in the external container. Do not configure the data sources in cache.xml . They are not guaranteed to get bound to the JNDI tree.
- Configure the external data sources in the external container. Do not configure the data sources in cache.xml . They are not guaranteed to get bound to the JNDI tree.
- Configure GemFire for any necessary transactional behavior in cache.xml. For example, enable copy-on-read and specify a transaction listener, if you need one. See Setting Global Copy on Read and Configuring Transaction Plug-In Event Handlers for details.
- Make sure that JTA transactions are not disabled for the regions that will participate in the transaction. See Turning Off JTA Transactions for details.
- Start the transaction through the external container.
- Initialize the GemFire cache. GemFire will automatically join the transaction.
- Execute operations in the cache and the database as usual.
- Commit the transaction through the external container.
Using GemFire as the "Last Resource" in a Container-Managed JTA Transaction
The "last resource" feature in certain 3rd party containers allows you to use one non-XAResource (such as GemFire ) in a transaction with multiple XAResources while ensuring consistency.
In the previous two JTA transaction use cases, if the GemFire member fails after the other data sources commit but before GemFire receives the afterCommit callback, GemFire and the other data sources may become inconsistent. To prevent this from occurring, you can use the container's "last resource optimization" feature (for example, in WebLogic and others). This feature allows you run transactions with GemFire set as the "last resource". Using GemFire as the last resource ensures that in the event of failure GemFire remains consistent with the other XAResources involved in the transaction.
To accomplish this, the application server container must use a JCA Resource Adapter to accomodate GemFire as the transaction's last resource. The transaction manager of the container first issues a "prepare" message to the participating XAResources. If the XAResources all accept the transaction, then the manager issues a "commit" instruction to the non-XAResource (in this case, GemFire .) The non-XAResource (in this case, GemFire ) participates as a local transaction resource. If the non-XAResource fails, then the transaction manager can rollback the XAResources.
How to Run JTA Transactions with GemFire as a "Last Resource"
See JCA Resource Adapter Example for an example of how to set up a transaction using the JCA Resource Adapter.
Using GemFire as the JTA Transaction Manager
You can also use GemFire as the JTA transaction manager.
GemFire ships with its own implementation of a JTA transaction manager. However, note that this implementation is not XA-compliant; therefore, it does not persist any state, which could lead to an inconsistent state after recovering a crashed member.
The GemFire JTA transaction manager is initialized when the GemFire cache is initialized. Until then, JTA is not available for use. The application starts a JTA transaction by using the UserTransaction.begin method. The UserTransaction object is the application’s handle to instruct the JTA transaction manager on what to do.
The GemFire JTA implementation also supports the J2EE Connector Architecture (JCA) ManagedConnectionFactory.
- Only one JDBC database instance per transaction is allowed, although you can have multiple connections to that database.
- Multiple threads cannot participate in a transaction.
- Transaction recovery after a crash is not supported.
How to Run a JTA Global Transaction Using GemFire as the JTA Transaction Manager
This topic describes how to run a JTA global transaction in GemFire .
To run a global transaction, perform the following steps: