@Override
  public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command)
      throws Throwable {
    if (ctx.getCacheTransaction() instanceof RemoteTransaction) {
      // If a commit is received for a transaction that doesn't have its 'lookedUpEntries' populated
      // we know for sure this transaction is 2PC and was received via state transfer but the
      // preceding PrepareCommand
      // was not received by local node because it was executed on the previous key owners. We need
      // to re-prepare
      // the transaction on local node to ensure its locks are acquired and lookedUpEntries is
      // properly populated.
      RemoteTransaction remoteTx = (RemoteTransaction) ctx.getCacheTransaction();
      if (remoteTx.isMissingLookedUpEntries()) {
        remoteTx.setMissingLookedUpEntries(false);

        PrepareCommand prepareCommand;
        if (useVersioning) {
          prepareCommand =
              commandFactory.buildVersionedPrepareCommand(
                  ctx.getGlobalTransaction(), ctx.getModifications(), false);
        } else {
          prepareCommand =
              commandFactory.buildPrepareCommand(
                  ctx.getGlobalTransaction(), ctx.getModifications(), false);
        }
        commandFactory.initializeReplicableCommand(prepareCommand, true);
        prepareCommand.setOrigin(ctx.getOrigin());
        log.tracef(
            "Replaying the transactions received as a result of state transfer %s", prepareCommand);
        prepareCommand.perform(null);
      }
    }

    return handleTxCommand(ctx, command);
  }
 private void applyTransactions(Address sender, Collection<TransactionInfo> transactions) {
   log.debugf(
       "Applying %d transactions for cache %s transferred from node %s",
       transactions.size(), cacheName, sender);
   if (isTransactional) {
     for (TransactionInfo transactionInfo : transactions) {
       CacheTransaction tx =
           transactionTable.getLocalTransaction(transactionInfo.getGlobalTransaction());
       if (tx == null) {
         tx = transactionTable.getRemoteTransaction(transactionInfo.getGlobalTransaction());
         if (tx == null) {
           tx =
               transactionTable.getOrCreateRemoteTransaction(
                   transactionInfo.getGlobalTransaction(), transactionInfo.getModifications());
           ((RemoteTransaction) tx).setMissingLookedUpEntries(true);
         }
       }
       for (Object key : transactionInfo.getLockedKeys()) {
         tx.addBackupLockForKey(key);
       }
     }
   }
 }