Transaction Management

Search XAP 7.0
Searching XAP 7.0.X Documentation
Browse XAP 7.0
Offline Documentation

Download latest offline documentation in HTML format:
xap-7.0.2-documentation.zip (12.3MB)

                                                              

Summary: OpenSpaces provides several implementations of Spring's PlatformTransactionManager allowing you to use the GigaSpaces and Jini Transaction Manager.

Overview

Spring Framework provides a transaction manager abstraction using the PlatformTransactionManager interface with several different built-in implementations, such as JDBC Data Source and JTA. GigaSpaces provides several implementations for Spring's PlatformTransactionManager, allowing you to use the GigaSpaces local and Jini Transaction Managers.

By implementing Spring's PlatformTransactionManager, The OpenSpaces API allows users to utilize Spring's rich support for declarative transaction management. The declarative transaction support can be easily utilized with the GigaSpace Interface.

Please note that when using Spring declarative transaction, a proxy is generated for the classes annotated with @Transactional methods. In such a case only external method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional.

In order to make The GigaSpace Interface transactional, the transaction manager must be provided to it when constructing the GigaSpace bean.
The following should be added to your pu.xml to enable the configuration of transactional behavior based on annotations:

<tx:annotation-driven transaction-manager="transactionManager"/>

GigaSpaces provides several transaction managers, and changing the implementation you work with is just a matter of changing the the configuration.

Transaction Manager Types

The section below lists the different types of transaction managers supported by GigaSpaces. Each transaction manager
implements Spring PlatformTransactionManager interface and therefore supports the Spring transaction framework (see below).

Local Jini Transaction Manager

GigaSpaces' built-in, high-performance, single space Local Transaction Manager supports transactions on a single space instance (with or without backups). It is the fastest and most recommended transaction manager.
When performing operations that space multiple space instances (i.e. writing objects to multiple space partitions in a partitioned topology), you should use the the distributed Jini Transaction Manager. Note that this can be avoided when designing your application according the SBA model, where your business logic is collocated with each space partition and performs operations on this partition only.

Here is an example of how to define a local transaction manager in your pu.xml or your code :

When defining a local transaction manager, the space bean is used as a transactional context handed over to the local transaction manager instance which requires it.

Timeout Values

The local transaction manager allows to set the default timeout value for transactions. A timeout value is used when a transaction is not committed/rolled back (for example due to JVM crash) to control when the transaction will be discarded. By default the timeout value is 60 and is set in seconds. Controlling the timeout value can be done as follows:

When using Spring declarative transaction management, a transaction timeout can be set on the transactional method using the @Transactional(timeout=1) annotation (a method for example). This timeout setting will be used as the timeout value for the transaction (note that this timeout value is set in seconds - per Spring spec). If no timeout is set, the default timeout set on the transaction manager is used.

When using Jini based transactions, a timeout value can be set for both the commit and abort operations. This values can also be set on the transaction manager.

Distributed Jini Transaction Manager

The distributed Jini Transaction Manager starts an embedded distributed (mahalo) Jini Transaction Manager, which is then wrapped with an implementation of the Spring PlatformTransactionManager. This transaction manager is used in order to perform distributed transactions spanning multiple space instances.

Below is an example of how it can be defined in a Spring application context:

Timeout Values

The Jini distributed (mahalo) transaction manager allows to set the default timeout value for transactions. A timeout value is used when a transaction is not committed/rolled back (for example due to JVM crash) to control when the transaction will be discarded. By default the timeout value is 60 and is set in seconds. Controlling the timeout value can be done using:

Time based Parameters Units:

  • The default-timeout parameter is specified in seconds
  • Other parameters such as the commit and abort timeout, lookup-timeout, and others are specified in millisecond

When using Spring declarative transaction management, a transaction timeout can be set on the transaction scope. For more details, see above.

When using Jini based transactions, a timeout value can be set for both the commit and abort operations. This values can also be set on the transaction manager.

Lookup Jini Transaction Manager

The lookup Jini Transaction Manager allows you to use the Jini lookup mechanism in order to lookup a Jini Transaction Manager that is present somewhere in the cluster (as opposed to being started locally in your application), which is then wrapped with an implementation of the Spring PlatformTransactionManager. This transaction manager is usually used in order to obtain a remote Jini Mahalo transaction manager for distributed transactions spanning multiple space instances.

Below is an example of how it can be defined in a Spring application context:

Timeout Values

The Jini lookup transaction manager allows to set the default timeout value for transactions. A timeout value is used when a transaction is not committed/rolled back (for example due to JVM crash) to control when the transaction will be discarded. By default the timeout value is 60 Sec and is set in seconds. Controlling the timeout value can be done using:

When using Spring declarative transaction management, a transaction timeout can be set on the transaction scope. For more details, see above.

When using Jini based transactions, a timeout value can be set for both the commit and abort operations. This values can also be set on the transaction manager.

Renewing Transactions

Both Local and Jini transactions allow you to configure automatic renewing of ongoing transactions. This feature is very handy when wanting to configure a long transaction timeout, and have it expire earlier in case of a complete failure (for example, JVM crash). Expiring the transaction is important so objects held under a transaction lock are released as soon as possible.

Here is an example of how this can be configured:

The above configuration creates a Local Transaction Manager with a pool of 2 transaction (lease) renewal managers (a single manager can handle multiple transactions, more managers allow for better concurrency). Each transaction is renewed every 1 second (1000 milliseconds) with an expected round trip time of 500 milliseconds. This means that a transaction with a timeout of 10 seconds is renewed 10 times (approximately) and if the JVM crashes, the transaction expires within a second (at most).

XA/JTA Support

GigaSpaces can be used within an XA transaction using JTA. The OpenSpaces API allows you to work with Spring's JTATransactionManager and provides support for declarative transaction management. Here is an example of how OpenSpaces JTA support can be used (using JOTM):

GigaSpaces JTA support uses the high-performance Local Transaction Manager internally. The Local Transaction Manager can only be used when performing operations against a single Space instance. When working with a clustered topology using a proxy that connects to the whole cluster, operations should be performed only against a single cluster member (controlled using routing index). Working with two different Spaces (and not different cluster members) is supported with JTA.

XA transactions should generally be avoided and not used. The overhead of managing a 2PC transaction over two or more resources is often times a performance killer. We recommend using well-known patterns in order to avoid it (such as duplicate detection).

How to Demarcate Transactions in Your Code

There are two ways to demarcate the transaction boundaries in your code:

  1. Annotate your methods with the Spring @Transactional annotation and configure Spring to process the annotation such that every call to the annotated methods will be automatically performed under a transaction. In such case the transaction starts before the method is called and commits when the method call returns. If an exception is thrown from the method the transaction is rolled back automatically. Note that you can control various aspects of the transaction by using the attributes of the @Transactional annotation. Please consult the Javadoc of this class for more details.
  2. Programmatically create the required transaction manager (see below) and a TransactionDefinition instance, and call the space operations you would to perform under a transaction.

Declarative Transaction Demarcation

Here is an example how a method should be annotated to support declarative transaction management:

@Transactional (propagation=Propagation.REQUIRED)
public void myTransactionalMethod(Object data) {
  gigaSpace.write(mySpaceObject);
  gigaSpace.take(mytemplate);
  ...
  }

To enable the declarative transaction management:

  1. In your processing unit XML, your pu.xml should include the <tx:annotation-driven> tag. See the below example for enabling the @Transactional annotation processing for the pu.xml. The system will search for @Transactional annotations on all of the beans in the pu.xml.
  2. For the transactional behavior to take effect, the calling code must be injected with the transactional bean. In the example below, we have the transactionalBean bean which annotates some of its methods with the @Transactional annotation. The callingBean is injected with it. Under the hood, Spring will wrap the transactionalBean with a transactional proxy that will initiate a transaction before the method is called and commit/rollback it according to the invocation result.
  3. The @Transactional annotation is only going to be applied for proxied beans, i.e. beans that have been processed by the framework and injected to other beans which use them.
  4. If you try to call an annotated method from within the same class for example (e.g. calling it on this), no transaction will be started since your code actually accesses direct reference and not a proxied bean.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:os-core="http://www.openspaces.org/schema/core"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:os-events="http://www.openspaces.org/schema/events"
       xmlns:os-remoting="http://www.openspaces.org/schema/remoting"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.openspaces.org/schema/core http://www.openspaces.org/schema/core/openspaces-core.xsd
       http://www.openspaces.org/schema/events http://www.openspaces.org/schema/events/openspaces-events.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd      
       http://www.openspaces.org/schema/remoting http://www.openspaces.org/schema/remoting/openspaces-remoting.xsd">

	<os-core:space id="space" url="/./space" />
	<os-core:giga-space id="gigaSpace" space="space" tx-manager="transactionManager"/>
	<!-- Defines a local Jini transaction manager. -->
	<os-core:local-tx-manager id="transactionManager" space="space"/>
        <bean id="transactionalBean" class="MyClass"/>
        <bean id="callingBean" class="MyOtherClass">
            <property name="myClass" ref="transactionalBean"/> 
        </bean>
	<tx:annotation-driven transaction-manager="transactionManager" /> 
</beans>

Note that you can also annotate beans exposed via space based remoting. If you include the <tx:annotation-driven> element in your pu.xml file, it will be processed as any other bean and the remoting mechanism will use the proxied instance, thus making the remote call to the bean transactional.

Programmatic Transaction Management

If you don't want to leverage Spring's declarative transaction management, or have an application that is not configured by Spring, you can start, commit and rollback transactions explicitly from within your code by using Spring's transaction API.

Here is how you should use the Transaction manager via the API:
1. Get a reference to the relevant PlatformTransactionManager:

LocalJiniTxManagerConfigurer
IJSpace space = new UrlSpaceConfigurer("/./space").space();
PlatformTransactionManager ptm = new LocalJiniTxManagerConfigurer(space).transactionManager();
GigaSpace gigaSpace = new GigaSpaceConfigurer(space).transactionManager(ptm).gigaSpace();

or

DistributedJiniTxManagerConfigurer
PlatformTransactionManager ptm = new DistributedJiniTxManagerConfigurer().transactionManager();

or

LookupJiniTxManagerConfigurer
PlatformTransactionManager ptm = new LookupJiniTxManagerConfigurer().lookupTimeout(5000).transactionManager();

2. Use the GigaSpace to execute space operations and rollback/commit using the PlatformTransactionManager created:

GigaSpace gigaSpace = ...//get reference to a GigaSpace instance
PlatformTransactionManager ptm = ... //get a reference to a GigaSpaces PlatformTransactionManager 
 // instance as described in step one above. 
 // Use the relevant type based on the nature of the business logic behavior.
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
//configure the definition...
TransactionStatus status = ptm.getTransaction(definition);
try {    
    //do things with the GigaSpace instance...
} 
catch (MyException e) {
    ptm.rollback(status);
    throw e;
}
ptm.commit(status);

You can also use Spring's TransactionTemplate if you prefer. This is documented in full in the Spring reference guide.

IMPORTANT: This is an old version of GigaSpaces XAP. Click here for the latest version.

Labels

 
(None)