@Test
  public void testTXListenerOnRedundant() {
    Host host = Host.getHost(0);
    VM datastore1 = host.getVM(0);
    VM datastore2 = host.getVM(1);
    VM client = host.getVM(2);
    int port = createRegionOnServer(datastore1, true, false, 1);
    createRegionOnServer(datastore2, false, false, 1);
    createClientRegion(client, port, true);

    class RedundantListener extends TransactionListenerAdapter {
      int invoked = 0;

      @Override
      public void afterCommit(TransactionEvent event) {
        invoked++;
      }
    }

    SerializableCallable registerTxListener = new SerializableCallable<Object>() {
      @Override
      public Object call() {
        getCache().getCacheTransactionManager().addListener(new RedundantListener());
        return null;
      }
    };

    datastore1.invoke(registerTxListener);
    datastore2.invoke(registerTxListener);

    client.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        Region<CustId, Customer> pr = getGemfireCache().getRegion(CUSTOMER);
        getGemfireCache().getCacheTransactionManager().begin();
        pr.put(new CustId(1), new Customer("name1", "address1"));
        getGemfireCache().getCacheTransactionManager().commit();
        return null;
      }
    });

    SerializableCallable listenerInvoked = new SerializableCallable<Object>() {
      @Override
      public Object call() {
        RedundantListener l =
            (RedundantListener) getCache().getCacheTransactionManager().getListeners()[0];
        return l.invoked;
      }
    };

    int listenerInvokedCount =
        (Integer) datastore1.invoke(listenerInvoked) + (Integer) datastore2.invoke(listenerInvoked);
    assertEquals(1, listenerInvokedCount);
  }
test has a client, two accessors and a datastore pool connects to two accessors. we then close
the server in first accessor and verify failover
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/ClientServerTransactionDUnitTest.java