Index: simplerunner/pom.xml
===================================================================
--- simplerunner/pom.xml	(revision 20)
+++ simplerunner/pom.xml	(revision 21)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>simplerunner</artifactId>
-	<version>1.4.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.0</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.4.4</geniusweb.version>
+		<geniusweb.version>1.5.0</geniusweb.version>
 	</properties>
 
Index: simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java
===================================================================
--- simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java	(revision 20)
+++ simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java	(revision 21)
@@ -3,4 +3,5 @@
 import java.io.IOException;
 import java.net.URI;
+import java.util.concurrent.ArrayBlockingQueue;
 
 import geniusweb.connection.ConnectionEnd;
@@ -22,4 +23,6 @@
 	// to be initialized
 	private Listener<OUT> handler = null;
+	private Thread handlerThread;
+	private ArrayBlockingQueue<OUT> messages = new ArrayBlockingQueue<OUT>(4);
 
 	/**
@@ -33,4 +36,5 @@
 		this.reference = reference;
 		this.uri = uri;
+
 	}
 
@@ -47,4 +51,20 @@
 		}
 		this.handler = newhandler;
+
+		handlerThread = new Thread(new Runnable() {
+
+			@Override
+			public void run() {
+				try {
+					while (true) {
+						handler.notifyChange(messages.take());
+					}
+				} catch (InterruptedException e) {
+					System.out.println("connection handler interrupted");
+				}
+			}
+		});
+
+		handlerThread.start();
 	}
 
@@ -55,5 +75,9 @@
 					"BasicConnection has not been initialized");
 		}
-		handler.notifyChange(data);
+		try {
+			messages.put(data);
+		} catch (InterruptedException e) {
+			throw new IOException(e);
+		}
 	}
 
@@ -70,5 +94,7 @@
 	@Override
 	public void close() {
-
+		handlerThread.interrupt();
+		handlerThread = null;
+		handler = null;
 	}
 
Index: simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java
===================================================================
--- simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java	(revision 20)
+++ simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java	(revision 21)
@@ -11,6 +11,6 @@
 import geniusweb.actions.Action;
 import geniusweb.actions.PartyId;
+import geniusweb.inform.Inform;
 import geniusweb.party.Party;
-import geniusweb.party.inform.Inform;
 import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
 import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
@@ -22,6 +22,4 @@
  * <code>classpath:org/my/package/class</code>
  * 
- * 
- *
  */
 public class ClassPathConnectionFactory implements ProtocolToPartyConnFactory {
Index: simplerunner/src/main/java/geniusweb/simplerunner/NegoRunner.java
===================================================================
--- simplerunner/src/main/java/geniusweb/simplerunner/NegoRunner.java	(revision 20)
+++ simplerunner/src/main/java/geniusweb/simplerunner/NegoRunner.java	(revision 21)
@@ -29,8 +29,19 @@
 	private final ProtocolToPartyConnFactory connectionfactory;
 	protected final Reporter log;
+	private boolean properlyStopped = false;
 	private final static ObjectMapper jackson = new ObjectMapper();
+	private final int LOOPTIME = 200;// ms
+	private long maxruntime;
 
+	/**
+	 * 
+	 * @param settings
+	 * @param connectionfactory
+	 * @param logger
+	 * @param maxruntime        limit in millisecs. Ignored if 0
+	 */
 	public NegoRunner(NegoSettings settings,
-			ProtocolToPartyConnFactory connectionfactory, Reporter logger) {
+			ProtocolToPartyConnFactory connectionfactory, Reporter logger,
+			long maxruntime) {
 		if (settings == null || connectionfactory == null) {
 			throw new NullPointerException("Arguments must be not null");
@@ -40,4 +51,9 @@
 		this.protocol = settings.getProtocol(log);
 		this.connectionfactory = connectionfactory;
+		this.maxruntime = maxruntime;
+	}
+
+	public boolean isProperlyStopped() {
+		return properlyStopped;
 	}
 
@@ -46,4 +62,14 @@
 		protocol.addListener(evt -> handle(evt));
 		protocol.start(connectionfactory);
+		long remainingtime = maxruntime;
+		while (!properlyStopped && (maxruntime == 0 || remainingtime > 0)) {
+			try {
+				Thread.sleep(LOOPTIME);
+				remainingtime -= LOOPTIME;
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+		}
+		System.out.println("end run");
 	}
 
@@ -56,7 +82,6 @@
 
 	protected void stop() {
-		Level level = protocol.getState().getError() == null ? Level.INFO
-				: Level.WARNING;
-		logFinal(level, protocol.getState());
+		logFinal(Level.INFO, protocol.getState());
+		properlyStopped = true;
 	}
 
@@ -88,10 +113,10 @@
 
 		NegoRunner runner = new NegoRunner(settings,
-				new ClassPathConnectionFactory(), new StdOutReporter());
+				new ClassPathConnectionFactory(), new StdOutReporter(), 0);
 		runner.run();
 	}
 
 	private static void showusage() {
-		System.err.println("GeniusWeb stand-alone runner. ");
+		System.err.println("GeniusWeb stand-alone runner.");
 		System.err.println("first argument should be <settings.json>.");
 		System.err.println(
@@ -100,4 +125,11 @@
 				"See the settings.json example file and the GeniusWeb wiki pages. ");
 
+	}
+
+	/**
+	 * @return protocol that runs/ran the session.
+	 */
+	public NegoProtocol getProtocol() {
+		return protocol;
 	}
 }
Index: simplerunner/src/test/java/geniusweb/simplerunner/ClassPathConnectionFactoryTest.java
===================================================================
--- simplerunner/src/test/java/geniusweb/simplerunner/ClassPathConnectionFactoryTest.java	(revision 20)
+++ simplerunner/src/test/java/geniusweb/simplerunner/ClassPathConnectionFactoryTest.java	(revision 21)
@@ -11,7 +11,6 @@
 import geniusweb.actions.Action;
 import geniusweb.connection.ConnectionEnd;
-import geniusweb.party.inform.Inform;
+import geniusweb.inform.Inform;
 import geniusweb.references.PartyRef;
-import geniusweb.simplerunner.ClassPathConnectionFactory;
 
 public class ClassPathConnectionFactoryTest {
Index: simplerunner/src/test/java/geniusweb/simplerunner/SessionRunnerE2ETest.java
===================================================================
--- simplerunner/src/test/java/geniusweb/simplerunner/SessionRunnerE2ETest.java	(revision 20)
+++ simplerunner/src/test/java/geniusweb/simplerunner/SessionRunnerE2ETest.java	(revision 21)
@@ -1,3 +1,5 @@
 package geniusweb.simplerunner;
+
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
@@ -27,4 +29,5 @@
 @RunWith(Parameterized.class)
 public class SessionRunnerE2ETest {
+	private static final int TEST_RUNTIME = 5000;
 	private final ObjectMapper jackson = new ObjectMapper();
 	private NegoRunner runner;
@@ -37,5 +40,6 @@
 				.asList(new Object[][] { { "src/test/resources/settings.json" },
 						{ "src/test/resources/settings2.json" },
-						{ "src/test/resources/shaoptoursettings.json" } });
+						{ "src/test/resources/shaoptoursettings.json" },
+						{ "src/test/resources/mopac.json" } });
 	}
 
@@ -53,5 +57,5 @@
 
 		runner = new NegoRunner(settings, new ClassPathConnectionFactory(),
-				logger);
+				logger, TEST_RUNTIME);
 
 	}
@@ -64,4 +68,6 @@
 	public void runTest() throws IOException {
 		runner.run();
+		assertTrue(runner.isProperlyStopped());
+		System.out.println("Final state:\n" + runner.getProtocol().getState());
 	}
 
Index: simplerunner/src/test/java/geniusweb/simplerunner/SessionRunnerTest.java
===================================================================
--- simplerunner/src/test/java/geniusweb/simplerunner/SessionRunnerTest.java	(revision 20)
+++ simplerunner/src/test/java/geniusweb/simplerunner/SessionRunnerTest.java	(revision 21)
@@ -16,4 +16,5 @@
 import org.mockito.ArgumentCaptor;
 
+import geniusweb.actions.PartyId;
 import geniusweb.protocol.CurrentNegoState;
 import geniusweb.protocol.NegoState;
@@ -29,5 +30,5 @@
 public class SessionRunnerTest {
 	private static final ProtocolException PROTOCOL_EXC = new ProtocolException(
-			"fake protocol exception", "test");
+			"fake protocol exception", new PartyId("test"));
 	private CurrentNegoState finishedEvent;
 	private final long NOW = 1000;
@@ -47,5 +48,5 @@
 	public void smokeTest() {
 		new NegoRunner(mock(SessionSettings.class),
-				mock(ProtocolToPartyConnFactory.class), logger);
+				mock(ProtocolToPartyConnFactory.class), logger, 5000);
 	}
 
@@ -59,5 +60,6 @@
 				ProtocolToPartyConnFactory.class);
 
-		NegoRunner runner = spy(new NegoRunner(settings, factory, logger));
+		NegoRunner runner = spy(
+				new NegoRunner(settings, factory, logger, 5000));
 		runner.run();
 
@@ -75,5 +77,4 @@
 		when(settings.getProtocol(any())).thenReturn(protocol);
 		SessionState state = mock(SessionState.class);
-		when(state.getError()).thenReturn(null);
 		when(protocol.getState()).thenReturn(state);
 		Reporter logger = mock(Reporter.class);
@@ -81,10 +82,11 @@
 		ProtocolToPartyConnFactory factory = mock(
 				ProtocolToPartyConnFactory.class);
-		NegoRunner runner = spy(new NegoRunner(settings, factory, logger) {
-			@Override
-			protected void logFinal(Level level, NegoState state) {
-				log.log(level, state.toString());
-			}
-		});
+		NegoRunner runner = spy(
+				new NegoRunner(settings, factory, logger, 5000) {
+					@Override
+					protected void logFinal(Level level, NegoState state) {
+						log.log(level, state.toString());
+					}
+				});
 		ArgumentCaptor<Listener> listener = ArgumentCaptor
 				.forClass(Listener.class);
@@ -107,15 +109,15 @@
 		when(settings.getProtocol(any())).thenReturn(protocol);
 		SessionState state = mock(SessionState.class);
-		when(state.getError()).thenReturn(PROTOCOL_EXC);
 		when(protocol.getState()).thenReturn(state);
 		@SuppressWarnings("unchecked")
 		ProtocolToPartyConnFactory factory = mock(
 				ProtocolToPartyConnFactory.class);
-		NegoRunner runner = spy(new NegoRunner(settings, factory, logger) {
-			@Override
-			protected void logFinal(Level level, NegoState state) {
-				log.log(level, state.toString());
-			}
-		});
+		NegoRunner runner = spy(
+				new NegoRunner(settings, factory, logger, 5000) {
+					@Override
+					protected void logFinal(Level level, NegoState state) {
+						log.log(level, state.toString());
+					}
+				});
 		ArgumentCaptor<Listener> listener = ArgumentCaptor
 				.forClass(Listener.class);
@@ -126,6 +128,8 @@
 		listener.getValue().notifyChange(finishedEvent);
 		verify(runner, times(1)).stop();
-		// check that the protocol error is logged properly
-		verify(logger, times(1)).log(eq(Level.WARNING), any(String.class));
+		// check final state is logged
+		String statestr = state.toString();
+		verify(logger, times(1)).log(any(), eq(statestr));
+
 	}
 
Index: simplerunner/src/test/resources/jobs/jobs1.json
===================================================================
--- simplerunner/src/test/resources/jobs/jobs1.json	(revision 20)
+++ simplerunner/src/test/resources/jobs/jobs1.json	(revision 21)
@@ -34,6 +34,6 @@
 				"discreteutils": {
 					"valueUtilities": {
-						"yes":1,
-						"no":0
+						"yes": 1,
+						"no": 0
 					}
 				}
@@ -42,6 +42,6 @@
 				"discreteutils": {
 					"valueUtilities": {
-						"yes":1,
-						"no":0
+						"yes": 1,
+						"no": 0
 					}
 				}
@@ -50,7 +50,7 @@
 				"discreteutils": {
 					"valueUtilities": {
-						"low":0,
-						"medium":0.5,
-						"high":1
+						"low": 0,
+						"medium": 0.5,
+						"high": 1
 					}
 				}
@@ -112,5 +112,15 @@
 			}
 		},
-		"name": "jobs1"
+		"name": "jobs1",
+		"reservationBid": {
+			"issuevalues": {
+				"salary": "3500",
+				"fte": "0.8",
+				"work from home": "1",
+				"lease car": "no",
+				"permanent contract": "yes",
+				"career development opportunities": "medium"
+			}
+		}
 	}
 }
Index: simplerunner/src/test/resources/jobs/jobs2.json
===================================================================
--- simplerunner/src/test/resources/jobs/jobs2.json	(revision 20)
+++ simplerunner/src/test/resources/jobs/jobs2.json	(revision 21)
@@ -34,6 +34,6 @@
 				"discreteutils": {
 					"valueUtilities": {
-						"yes":0,
-						"no":1
+						"yes": 0,
+						"no": 1
 					}
 				}
@@ -42,6 +42,6 @@
 				"discreteutils": {
 					"valueUtilities": {
-						"yes":0.23809523809523808,
-						"no":0.761904761904762
+						"yes": 0.23809523809523808,
+						"no": 0.761904761904762
 					}
 				}
@@ -50,7 +50,7 @@
 				"discreteutils": {
 					"valueUtilities": {
-						"low":1.0,
-						"medium":0.5,
-						"high":0
+						"low": 1.0,
+						"medium": 0.5,
+						"high": 0
 					}
 				}
@@ -112,5 +112,15 @@
 			}
 		},
-		"name": "jobs2"
+		"name": "jobs2",
+		"reservationBid": {
+			"issuevalues": {
+				"salary": "3000",
+				"fte": "0.8",
+				"work from home": "0",
+				"lease car": "no",
+				"permanent contract": "no",
+				"career development opportunities": "medium"
+			}
+		}
 	}
 }
Index: simplerunner/src/test/resources/mopac.json
===================================================================
--- simplerunner/src/test/resources/mopac.json	(revision 21)
+++ simplerunner/src/test/resources/mopac.json	(revision 21)
@@ -0,0 +1,17 @@
+{
+	"MOPACSettings": {
+		"participants": [{
+			"party": {"partyref":"classpath:geniusweb.exampleparties.randomparty.RandomParty", "parameters":{"power":1}},
+			"profile": "file:src/test/resources/jobs/jobs1.json"
+		}, {
+			"party": {"partyref":"classpath:geniusweb.exampleparties.randomparty.RandomParty", "parameters":{"power":1}},
+			"profile": "file:src/test/resources/jobs/jobs2.json"
+		}],
+		"deadline": {
+			"deadlinetime": {
+				"durationms": 2000000
+			}
+		},
+		"votingevaluator":{"LargestAgreementsLoop":{}}
+	}
+}
Index: simplerunner/src/test/resources/shaoptoursettings.json
===================================================================
--- simplerunner/src/test/resources/shaoptoursettings.json	(revision 20)
+++ simplerunner/src/test/resources/shaoptoursettings.json	(revision 21)
@@ -34,5 +34,5 @@
 			{
 				"ProfileList": [
-					"file:src/test/resources/jobs/jobs1partial.json?partial=10",
+					"file:src/test/resources/jobs/jobs1partial.json",
 					"file:src/test/resources/jobs/jobs1partial.json"
 					
@@ -41,5 +41,5 @@
 			{
 				"ProfileList": [
-					"file:src/test/resources/jobs/jobs2.json?partial=15",
+					"file:src/test/resources/jobs/jobs2.json",
 					"file:src/test/resources/jobs/jobs2.json"
 					
@@ -55,5 +55,5 @@
 					"deadlinerounds": {
 						"rounds": 10,
-						"durationms": 10000
+						"durationms": 1000
 					}
 				}
