I am running simple test case based on one of the Infinispan unit tests. In my test I expect to receive CacheException
when replication timeouts in my cluster.
I use pessimistic transaction locking and exception is not thrown in this case for some reason. If I comment pessimistic locking I get exception as expected.
@Test(groups = "functional", testName = "replication.ReplicationExceptionTest")
public class ReplicationExceptionTest extends MultipleCacheManagersTest {
protected void createCacheManagers() {
ConfigurationBuilder configuration = getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, true);
configuration.locking()
.lockAcquisitionTimeout(60000l)
.transaction().transactionManagerLookup(new DummyTransactionManagerLookup());
// uncomment this line and exception is not thrown for some reason
//.lockingMode(LockingMode.PESSIMISTIC);
createClusteredCaches(2, configuration);
waitForClusterToForm();
}
@Test(groups = "functional", expectedExceptions = { CacheException.class })
public void testSyncReplTimeout() {
AdvancedCache cache1 = cache(0).getAdvancedCache();
AdvancedCache cache2 = cache(1).getAdvancedCache();
cache2.addInterceptor(new CommandInterceptor() {
@Override
protected Object handleDefault(InvocationContext ctx, VisitableCommand cmd)
throws Throwable {
// Add a delay
Thread.sleep(100);
return super.handleDefault(ctx, cmd);
}
}, 0);
cache1.getCacheConfiguration().clustering().sync().replTimeout(10);
cache2.getCacheConfiguration().clustering().sync().replTimeout(10);
TestingUtil.blockUntilViewsReceived(10000, cache1, cache2);
cache1.put("k", "v");
}
}
Can someone help me understand why it is hiding exception with pessimistic locking enabled and how to fix that?
Update: I am using Infinispan 5.3.0.Final.
It's because Infinispan registers itself with the transaction manager by default as a "synchronization" instead of a full XA resource. Synchronizations are not allowed to throw XAExceptions in their afterCompletion()
methods, and the transaction managers (including DummyTransactionManagerLookup
) swallow any runtime exceptions.
In optimistic mode, the keys and values are replicated during beforeCompletion()
, which is allowed to throw an exception in order to cancel the transaction.
In pessimistic mode, you should configure Infinispan to register as an XA resource instead:
configuration.transaction().useSynchronization(false);
Edit: By default, DummyTransactionManager
doesn't support XA transactions, so you also need to configure it for XA (or even better, use Narayana):
DummyTransactionManager.getInstance().setUseXaXid(true);