@Test
  public void testJTASynchronization()
      throws CacheException, javax.transaction.NotSupportedException,
      javax.transaction.RollbackException, javax.transaction.SystemException,
      javax.transaction.HeuristicMixedException, javax.transaction.HeuristicRollbackException {

    javax.transaction.TransactionManager jtaTxMgr = cache.getJTATransactionManager();
    TransactionListener tl = new TransactionListener() {
      @Override
      public void afterCommit(TransactionEvent event) {
        ++listenerAfterCommit;
        te = event;
      }

      @Override
      public void afterFailedCommit(TransactionEvent event) {
        ++listenerAfterFailedCommit;
        te = event;
      }

      @Override
      public void afterRollback(TransactionEvent event) {
        ++listenerAfterRollback;
        te = event;
      }

      @Override
      public void close() {
        ++listenerClose;
      }
    };

    txMgr.addListener(tl);
    Synchronization gfTXSync;

    // Test successful JTA commit
    jtaTxMgr.begin();
    txMgr.begin();
    {
      TXManagerImpl gfTxMgrImpl = (TXManagerImpl) txMgr;
      gfTXSync = gfTxMgrImpl.getTXState();
    }
    jtaTxMgr.getTransaction().registerSynchronization(gfTXSync);
    assertEquals(0, listenerAfterCommit);
    cache.getLogger().info("SWAP:doingCreate");
    region.create("syncKey1", "syncVal1");
    jtaTxMgr.commit();
    assertEquals(1, listenerAfterCommit);
    assertEquals("syncVal1", region.getEntry("syncKey1").getValue());

    try {
      txMgr.commit();
      fail("JTA Cache Manager should have called commit!");
    } catch (VirtualMachineError e) {
      SystemFailure.initiateFailure(e);
      throw e;
    } catch (Throwable ignored) {
    }

    // Test JTA rollback
    jtaTxMgr.begin();
    txMgr.begin();
    {
      TXManagerImpl gfTxMgrImpl = (TXManagerImpl) txMgr;
      gfTXSync = gfTxMgrImpl.getTXState();
    }
    jtaTxMgr.getTransaction().registerSynchronization(gfTXSync);
    assertEquals(0, listenerAfterRollback);
    region.put("syncKey2", "syncVal2");
    jtaTxMgr.rollback();
    assertEquals(1, listenerAfterRollback);
    assertTrue(!region.containsKey("syncKey2"));

    // Test failed JTA commit with suspend
    jtaTxMgr.begin();
    txMgr.begin();
    {
      TXManagerImpl gfTxMgrImpl = (TXManagerImpl) txMgr;
      gfTXSync = gfTxMgrImpl.getTXState();
      jtaTxMgr.getTransaction().registerSynchronization(gfTXSync);
      assertEquals(0, listenerAfterFailedCommit);
      region.put("syncKey3", "syncVal3");
      assertEquals("syncVal3", region.getEntry("syncKey3").getValue());

      TXStateProxy gfTx = gfTxMgrImpl.pauseTransaction();
      javax.transaction.Transaction jtaTx = jtaTxMgr.suspend();
      assertNull(jtaTxMgr.getTransaction());
      region.put("syncKey3", "syncVal4");
      assertEquals("syncVal4", region.getEntry("syncKey3").getValue());
      gfTxMgrImpl.unpauseTransaction(gfTx);
      try {
        jtaTxMgr.resume(jtaTx);
      } catch (Exception failure) {
        fail("JTA resume failed");
      }
      assertNotNull(jtaTxMgr.getTransaction());
    }
    assertEquals("syncVal3", region.getEntry("syncKey3").getValue());
    try {
      jtaTxMgr.commit();
      fail("Expected JTA manager conflict exception!");
    } catch (VirtualMachineError e) {
      SystemFailure.initiateFailure(e);
      throw e;
    } catch (Throwable ignored) {
    }
    assertEquals(1, listenerAfterFailedCommit);
    assertEquals("syncVal4", region.getEntry("syncKey3").getValue());


    // Test failed JTA commit with a new thread
    jtaTxMgr.begin();
    txMgr.begin();
    {
      TXManagerImpl gfTxMgrImpl = (TXManagerImpl) txMgr;
      gfTXSync = gfTxMgrImpl.getTXState();
      jtaTxMgr.getTransaction().registerSynchronization(gfTXSync);
      assertEquals(1, listenerAfterFailedCommit);
      region.put("syncKey4", "syncVal3");
      assertEquals("syncVal3", region.getEntry("syncKey4").getValue());

      // Create a new thread and have it update the same key, causing
      // a conflict
      final int[] signal = {0};
      Thread t = new Thread("non-TX conflict generator") {
        @Override
        public void run() {
          try {
            region.put("syncKey4", "syncVal4");
            while (true) {
              synchronized (signal) {
                signal[0] = 1;
                signal.notify();
                signal.wait();
                if (signal[0] == 0) {
                  break;
                }
              }
            }
          } catch (Exception error) {
            fail("Non-tx thread failure due to: " + error);
          }
        }
      };
      t.start();
      try {
        while (true) {
          synchronized (signal) {
            if (signal[0] == 1) {
              signal[0] = 0;
              signal.notify();
              break;
            } else {
              signal.wait();
            }
          }
        }
      } catch (InterruptedException dangit) {
        fail("Tx thread waiting for non-tx thread failed due to : " + dangit);
      }
      assertEquals("syncVal3", region.getEntry("syncKey4").getValue());
    }
    try {
      jtaTxMgr.commit();
      fail("Expected JTA manager conflict exception!");
    } catch (javax.transaction.HeuristicRollbackException ignored) {
    } catch (javax.transaction.RollbackException ignored) {
    } catch (VirtualMachineError e) {
      SystemFailure.initiateFailure(e);
      throw e;
    } catch (Throwable yuk) {
      fail("Did not expect this throwable from JTA commit: " + yuk);
    }
    assertEquals(2, listenerAfterFailedCommit);
    assertEquals("syncVal4", region.getEntry("syncKey4").getValue());

    txMgr.removeListener(tl);
  }
Test to make sure CacheListener callbacks are called in place with the CacheEvents properly
constructed
geode-core/src/integrationTest/java/org/apache/geode/TXJUnitTest.java