Rollback a transaction after a runtime exception during commit
suenda Sep 18, 2018 9:43 AMI use transaction to update several caches atomically. However, recently I have found that a runtime exception thrown during the commit phase does not rollback the transaction. A HeuristicMixedException is thrown by the transactionManager and a part of the transaction is commited.
I was able to reproduce the scenario in a test :
@Test
public void testRollBack() {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder
.clustering().cacheMode(CacheMode.DIST_SYNC)
.transaction()
.transactionMode(TransactionMode.TRANSACTIONAL)
.transactionManagerLookup(new JBossStandaloneJTAManagerLookup()).lockingMode(LockingMode.OPTIMISTIC)
.persistence().addStore(MyCacheStoreConfigurationBuilder.class)
.fetchPersistentState(true)
;
Configuration conf = builder.build();
GlobalConfiguration gcb = new GlobalConfigurationBuilder()
.transport()
.defaultTransport()
.clusterName("TEST_CLUSTER")
.defaultCacheName("default").build();
DefaultCacheManager cacheManager = new DefaultCacheManager(gcb, conf);
Cache<idrevision, article=""> reference = cacheManager.getCache("reference");
Cache<uuid, long=""> latestHit = cacheManager.getCache("hit");
TransactionManager transactionManager = reference.getAdvancedCache().getTransactionManager();
try {
transactionManager.begin();
} catch (NotSupportedException | SystemException e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
return;
}
Article article = new Article();
article.setId(UUID.randomUUID());
article.setRevision(1L);
article.setContent("Content");
try {
latestHit.put(article.getId(), System.currentTimeMillis());
reference.put(article.getIdRevision(), article);
} catch (Exception e) {
try {
transactionManager.rollback();
} catch (IllegalStateException | SecurityException | SystemException e1) {
e1.printStackTrace();
return;
}
}
try {
// The CacheStore MyCacheStore throws a IllegalStateException while
// writing the Article object.
transactionManager.commit();
} catch (SecurityException | IllegalStateException | RollbackException | HeuristicRollbackException
| SystemException e) {
e.printStackTrace();
} catch (HeuristicMixedException e) {
// the exception thrown by TransactionManager
e.printStackTrace();
}
Long hit = latestHit.get(article.getId());
assertThat("Rollback failed", hit, nullValue());
}The test above fails and I see that one of the caches is updated while the other is not. Is there any way to rollback the transaction?
I am using Infinispan 9.0.1.Final and narayana-jta 5.0.3.Final as the Transaction Manager.
Please see the zip attachment for the test project for code. To run my test, type : mvn clean test -Dtest=TestTransaction