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