@Before
	public void setUp() throws Exception {
		committed = false;

		context1 = TestUtil.createContext("/META-INF/spring/node1.xml");
		context2 = TestUtil.createContext("/META-INF/spring/node2.xml");
		context3 = TestUtil.createContext("/META-INF/spring/node3.xml");
		contextConfig = TestUtil.createContext("/META-INF/spring/config.xml");
		contextClient1 = TestUtil.createContext("/META-INF/spring/client.xml");
		contextClient2 = TestUtil.createContext("/META-INF/spring/client.xml");
		
		// Paxos Group A
		leaderA = (PaxosLeader) context1.getBean("protocolAL");
		followerA = (PaxosFollower) context1.getBean("protocolA1");
		followerA.addListener(new ProposalListener() {
			@Override
			public void notify(long id, Operation operation) {
				log.debug("notified Paxos Group A");
				if(operation instanceof PaxosPrepareOperation) {
					// prepare
					try {
						lockA.lock(operation.getId());
						participantA.acceptPrepare(((PaxosPrepareOperation) operation).transactionId);
					} catch(Exception e) {
						participantA.declinePrepare(((PaxosPrepareOperation) operation).transactionId);
					}
				} else if(operation instanceof PaxosCommitOperation) {
					// commit
					sleep(200);
					lockA.unlock();
					participantA.commitTransaction(((PaxosCommitOperation) operation).transactionId);
				}  else if(operation instanceof PaxosAbortOperation) {
					// abort
					lockA.unlock();
					participantA.abortTransaction(((PaxosAbortOperation) operation).transactionId);
				} else {
					log.error("unknown operation {}", operation.getId());
				}
			}
		});
		lockA = new LockManager();
		
		// Paxos Group B
		leaderB = (PaxosLeader) context2.getBean("protocolBL");
		followerB = (PaxosFollower) context2.getBean("protocolB2");
		followerB.addListener(new ProposalListener() {
			@Override
			public void notify(long id, Operation operation) {
				log.debug("notified Paxos Group B");
				if(operation instanceof PaxosPrepareOperation) {
					// prepare
					try {
						lockB.lock(operation.getId());
						participantB.acceptPrepare(((PaxosPrepareOperation) operation).transactionId);
					} catch(Exception e) {
						participantB.declinePrepare(((PaxosPrepareOperation) operation).transactionId);
					}
				} else if(operation instanceof PaxosCommitOperation) {
					// commit
					sleep(200);
					lockB.unlock();
					participantB.commitTransaction(((PaxosCommitOperation) operation).transactionId);
				}  else if(operation instanceof PaxosAbortOperation) {
					// abort
					lockB.unlock();
					participantB.abortTransaction(((PaxosAbortOperation) operation).transactionId);
				} else {
					log.error("unknown operation {}", operation.getId());
				}
			}
		});
		lockB = new LockManager();
		
		// Two Phase Commit
		coordinator = (TwoPhaseCommitCoordinator) context2.getBean("protocolTpcL");
		
		participantA = (TwoPhaseCommitParticipant) context1.getBean("protocolTpcA");
		participantA.setExecutor(new TransactionExecutor() {
			@Override
			public void prepare(long id, Operation operation) {
				leaderA.addProposal(new PaxosPrepareOperation(operation.getId(), id));
			}
			public void commit(long id, Operation operation) {
				leaderA.addProposal(new PaxosCommitOperation(operation.getId(), id));
			}
			@Override
			public void abort(long id, Operation operation) {
				leaderA.addProposal(new PaxosAbortOperation(operation.getId(), id));
			}
		});
		
		participantB = (TwoPhaseCommitParticipant) context2.getBean("protocolTpcB");
		participantB.setExecutor(new TransactionExecutor() {
			@Override
			public void prepare(long id, Operation operation) {
				leaderB.addProposal(new PaxosPrepareOperation(operation.getId(), id));
			}
			public void commit(long id, Operation operation) {
				leaderB.addProposal(new PaxosCommitOperation(operation.getId(), id));
			}
			@Override
			public void abort(long id, Operation operation) {
				leaderB.addProposal(new PaxosAbortOperation(operation.getId(), id));
			}
		});
		

		followerA.addListener(new ProposalListener() {
			@Override
			public void notify(long id, Operation operation) {
				committed = true;
			}
		});
		
		// set up servers
		setupModerator(context1, "serverAL", "pgA");
		setupModerator(context1, "serverA1", "pgA");
		setupModerator(context1, "serverB1", "pgB");
		setupModerator(context1, "serverTpcA", "tpc");

		setupModerator(context2, "serverA2", "pgA");
		setupModerator(context2, "serverBL", "pgB");
		setupModerator(context2, "serverB2", "pgB");
		setupModerator(context2, "serverTpcB", "tpc");
		setupModerator(context2, "serverTpcL", "tpc");

		setupModerator(context3, "serverA3", "pgA");
		setupModerator(context3, "serverB3", "pgB");
		
		// set up clients
		client1 = (TransactionEndpoint)contextClient1.getBean("smanner");
		client2 = (TransactionEndpoint)contextClient2.getBean("smanner");

	}