0
votes

I have hooked Ehcache into my JTA transaction manager (provided by Atomikos) using the setting cacheConfiguration.setTransactionalMode("xa");, and am receiving the following error approximately 15 seconds after my application starts up:

Caused by: net.sf.ehcache.transaction.TransactionTimeoutException: transaction [0] timed out
    at net.sf.ehcache.transaction.local.LocalTransactionStore.assertNotTimedOut(LocalTransactionStore.java:108) ~[ehcache-2.9.0.jar:2.9.0]
    at net.sf.ehcache.transaction.local.LocalTransactionStore.remove(LocalTransactionStore.java:391) ~[ehcache-2.9.0.jar:2.9.0]
    at net.sf.ehcache.transaction.local.JtaLocalTransactionStore.remove(JtaLocalTransactionStore.java:375) ~[ehcache-2.9.0.jar:2.9.0]
    at net.sf.ehcache.store.AbstractCopyingCacheStore.remove(AbstractCopyingCacheStore.java:110) ~[ehcache-2.9.0.jar:2.9.0]
    at net.sf.ehcache.store.TxCopyingCacheStore.remove(TxCopyingCacheStore.java:33) ~[ehcache-2.9.0.jar:2.9.0]
    at net.sf.ehcache.Cache.removeInternal(Cache.java:2401) ~[ehcache-2.9.0.jar:2.9.0]
    at net.sf.ehcache.Cache.remove(Cache.java:2306) ~[ehcache-2.9.0.jar:2.9.0]
    at net.sf.ehcache.Cache.remove(Cache.java:2224) ~[ehcache-2.9.0.jar:2.9.0]

When my app starts for the first time it performs some initial set up within a single transaction which takes approximately 60 seconds to complete. Consequently I need to increase the 15-second timeout to be a bigger value, but cannot find where this is controlled. From looking at the Ehcache documentation it seems this should be controlled by JTA, but I've already set the default timeout for UserTransaction and TransactionManager:

@Bean
public UserTransaction userTransaction() throws SystemException {

    UserTransactionImp uti = new UserTransactionImp();
    uti.setTransactionTimeout(120000);

    return uti;
}

@Bean(initMethod = "init", destroyMethod = "close")
public TransactionManager transactionManager() throws SystemException {

    UserTransactionManager utm = new UserTransactionManager();
    utm.setForceShutdown(false);
    utm.setTransactionTimeout(120000);

    return utm;
}

Any pointers would be appreciated.

2

2 Answers

0
votes

From looking at the code, I believe Ehcache will need to be configured with its own transaction timeout.

You can do this at the CacheManager level configuration.

In xml:

<ehcache ... defaultTransactionTimeoutInSeconds="120" ...>
  ...
</ehcache>

or in code:

new Configuration().defaultTransactionTimeoutInSeconds(120);
0
votes

You should make your timeout a Spring Environment property, so it can be referenced elsewhere.

Also, Spring's 'org.springframework.cache.ehcache.EhCacheManagerFactoryBean' does not expose a setter for defaultTransactionTimeoutSeconds to be able to modify the "Configuration" before Spring creates the CacheManager.

To resolve your issue, I created a custom EhCacheManagerFactoryBean rather than using Spring's. I added the new attribute, getter, and setter I needed.

// new attribute
private int defaultTransactionTimeoutSeconds;

public void setDefaultTransactionTimeoutSeconds(int value) {
   defaultTransactionTimeoutSeconds = value;
}

public int getDefaultTransactionTimeoutSeconds() {
   return defaultTransactionTimeoutSeconds;
}

Inject the value from your Spring Environment. Then, in the afterPropertiesSet() I code this:

Configuration configuration = (this.configLocation != null ?
            EhCacheManagerUtils.parseConfiguration(this.configLocation) : ConfigurationFactory.parseConfiguration());
        configuration.setDefaultTransactionTimeoutInSeconds(this.defaultTransactionTimeoutInSeconds);