Source:
private void crossCacheTransactionInAnotherThreadContinued() throws Exception { Ignite ignite1 = ignite(0); final IgniteTransactions transactions = ignite1.transactions(); final IgniteCache<String, Integer> cache = ignite1.getOrCreateCache(cacheConfiguration(null).setName("testCache")); final IgniteCache<String, Integer> cache2 = ignite1.getOrCreateCache(cacheConfiguration(null).setName("testCache2")); final Transaction tx = transactions.txStart(transactionConcurrency, transactionIsolation); cache.put("key1", 1); cache2.put("key2", 2); cache.put("key1'", 1); tx.suspend(); IgniteInternalFuture<Boolean> fut = GridTestUtils.runAsync(new Callable<Boolean>() { @Override public Boolean call() throws Exception { Assert.assertNull(transactions.tx()); Assert.assertEquals(TransactionState.SUSPENDED, tx.state()); tx.resume(); Assert.assertEquals(TransactionState.ACTIVE, tx.state()); cache.put("key3", 3); cache2.put("key2'", 2); cache2.remove("key2"); tx.suspend(); return true; } }); try { fut.get(); } catch (IgniteCheckedException e) { e.printStackTrace(); fail("Transaction in another thread failed"); } Assert.assertNull(transactions.tx()); Assert.assertEquals(TransactionState.SUSPENDED, tx.state()); tx.resume(); Assert.assertEquals(TransactionState.ACTIVE, tx.state()); cache.remove("key1'", 1); cache2.remove("key2'", 2); cache.put("key3'", 3); tx.commit(); Assert.assertEquals(TransactionState.COMMITTED, tx.state()); Assert.assertEquals((long)1, (long)cache.get("key1")); Assert.assertEquals((long)3, (long)cache.get("key3")); Assert.assertEquals((long)3, (long)cache.get("key3'")); Assert.assertFalse(cache2.containsKey("key2")); Assert.assertFalse(cache2.containsKey("key2'")); Assert.assertFalse(cache.containsKey("key1'")); cache.removeAll(); cache2.removeAll(); }

Target:
private void crossCacheTransactionInAnotherThreadContinued() throws IgniteCheckedException { Ignite ignite = ignite(txInitiatorNodeId); final IgniteTransactions transactions = ignite.transactions(); final IgniteCache<String, Integer> cache1 = ignite.getOrCreateCache(getCacheConfiguration().setName(TEST_CACHE_NAME)); final IgniteCache<String, Integer> cache2 = ignite.getOrCreateCache(getCacheConfiguration().setName(TEST_CACHE_NAME2)); final Transaction tx = transactions.txStart(TransactionConcurrency.OPTIMISTIC, transactionIsolation); cache1.put("key1", 1); cache2.put("key2", 2); cache1.put("key1'", 1); tx.suspend(); IgniteInternalFuture<Boolean> fut = GridTestUtils.runAsync(new Callable<Boolean>() { @Override public Boolean call() throws Exception { assertNull(transactions.tx()); assertEquals(TransactionState.SUSPENDED, tx.state()); tx.resume(); assertEquals(TransactionState.ACTIVE, tx.state()); cache1.put("key3", 3); cache2.put("key2'", 2); cache2.remove("key2"); tx.suspend(); return true; } }); fut.get(5000); assertNull(transactions.tx()); assertEquals(TransactionState.SUSPENDED, tx.state()); tx.resume(); assertEquals(TransactionState.ACTIVE, tx.state()); cache1.remove("key1'", 1); cache2.remove("key2'", 2); cache1.put("key3'", 3); tx.commit(); assertEquals(TransactionState.COMMITTED, tx.state()); assertEquals((long)1, (long)cache1.get("key1")); assertEquals((long)3, (long)cache1.get("key3")); assertEquals((long)3, (long)cache1.get("key3'")); assertFalse(cache2.containsKey("key2")); assertFalse(cache2.containsKey("key2'")); assertFalse(cache1.containsKey("key1'")); cache1.removeAll(); cache2.removeAll(); }