Strict XA (Support for All JTA Components)
Note that Ehcache as an XA resource:
- Has an isolation level of ReadCommitted.
- Updates the underlying store asynchronously,
potentially creating update conflicts. With this optimistic locking
approach, Ehcache might force the transaction manager to roll back
the entire transaction if a
commit()
generates a RollbackException (indicating a conflict). - Can work alongside other resources such as JDBC or JMS resources.
- Guarantees that its data is always synchronized with other XA resources.
- Can be configured on a per-cache basis (transactional and non-transactional caches can exist in the same configuration).
- Automatically performs enlistment.
- Can be used standalone or integrated with frameworks such as Hibernate.
- Is tested with the most common transaction managers by Atomikos, Bitronix, JBoss, WebLogic, and others.
Configuration
To configure a cache as an XA resource
able to participate in JTA transactions, the following <cache>
attributes
must be set as shown:
- transactionalMode="xa_strict"
- copyOnRead="true"
- copyOnWrite="true"
In addition, the <cache>
sub-element <terracotta>
must
not have clustering disabled.
For example, the following cache is configured for JTA transactions with strict XA:
<cache name="com.my.package.Foo"
maxEntriesLocalHeap="500"
eternal="false"
copyOnRead="true"
copyOnWrite="true"
consistency="strong"
transactionalMode="xa_strict">
<persistence strategy="distributed"/>
<terracotta />
</cache>
Any other XA resource that could be involved in the transaction, such as a database, must also be configured to be XA compliant.
Usage
Your application can directly use a transactional cache in transactions. This usage must occur after the transaction manager has been set to start a new transaction and before it has ended the transaction.
For example:
...
myTransactionMan.begin();
Cache fooCache = cacheManager.getCache("Foo");
fooCache.put("1", "Bar");
myTransactionMan.commit();
...
If more than one transaction writes to a cache, it is possible for an XA transaction to fail. See Avoiding XA Commit Failures With Atomic Methods.
Setting Up Transactional Caches in Hibernate {#45557}
If your application is using JTA, you can set up transactional caches in a second-level cache with Ehcache for Hibernate. To do so, ensure the following:
Ehcache
- You are using Ehcache 2.1.0 or higher.
- The attribute
transactionalMode
is set to "xa" or "xa-strict". -
The cache is clustered (the <cache> element has the sub-element <terracotta clustered="true">). For example, the following cache is configured to be transactional:
<cache name="com.my.package.Foo" ... transactionalMode="xa"> <terracotta /> </cache>
-
The cache UpdateTimestampsCache is not configured to be transactional. Hibernate updates to
org.hibernate.cache.UpdateTimestampsCache
prevent it from being able to participate in XA transactions.
Hibernate
- You are using Hibernate 3.3.
- The factory class used for the second-level
cache is
net.sf.ehcache.hibernate.EhCacheRegionFactory
. - Query cache is turned off.
- The value of
current_session_context_class
isjta
. - The value of
transaction.manager_lookup_class
is the name of a TransactionManagerLookup class (see your Transaction Manager). - The value of
transaction.factory_class
is the name of a TransactionFactory class to use with the Hibernate Transaction API. - The cache concurrency strategy is set
to TRANSACTIONAL. For example, to set the cache concurrency strategy
for
com.my.package.Foo
inhibernate.cfg.xml
:<class-cache class="com.my.package.Foo" usage="transactional"/>
Or in a Hibernate mapping file (hbm file):
<cache usage="transactional"/>
Or using annotations:
@Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL) public class Foo {...}