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 is jta.
  • 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 in hibernate.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 {...}
Important: WARNING: Use the TRANSACTIONAL concurrency strategy with transactional caches only. Using with other types of caches will cause errors.