Index: src/main/java/geniusweb/partiesserver/AvailablePartiesUpdater.java
===================================================================
--- src/main/java/geniusweb/partiesserver/AvailablePartiesUpdater.java	(revision 30)
+++ src/main/java/geniusweb/partiesserver/AvailablePartiesUpdater.java	(revision 31)
@@ -3,9 +3,7 @@
 import java.io.File;
 import java.io.IOException;
-import java.net.JarURLConnection;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
 import java.net.URL;
-import java.net.URLClassLoader;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -14,4 +12,5 @@
 import java.util.logging.Level;
 
+import geniusweb.partiesserver.repository.AvailableJavaParty;
 import geniusweb.partiesserver.repository.AvailablePartiesRepo;
 import geniusweb.partiesserver.repository.AvailableParty;
@@ -24,5 +23,4 @@
 import tudelft.utilities.logging.Reporter;
 import tudelft.utilities.repository.Repository;
-import java.util.jar.Attributes;
 
 /**
@@ -110,5 +108,6 @@
 	private void tryLoad(File file) {
 		try {
-			repository.put(new AvailableParty(getShortName(file), load(file)));
+			repository.put(
+					new AvailableJavaParty(getShortName(file), load(file)));
 		} catch (Throwable e) {
 			log.log(Level.WARNING, "Can not load class from file " + file, e);
@@ -226,4 +225,2 @@
 	}
 }
-
-
Index: src/main/java/geniusweb/partiesserver/repository/AvailableJavaParty.java
===================================================================
--- src/main/java/geniusweb/partiesserver/repository/AvailableJavaParty.java	(revision 31)
+++ src/main/java/geniusweb/partiesserver/repository/AvailableJavaParty.java	(revision 31)
@@ -0,0 +1,124 @@
+package geniusweb.partiesserver.repository;
+
+import geniusweb.actions.PartyId;
+import geniusweb.party.Capabilities;
+import geniusweb.party.Party;
+
+/**
+ * An approved and ready to run party.
+ */
+public class AvailableJavaParty implements AvailableParty {
+
+	private final Class<? extends Party> partyclass;
+	private final String name;
+	private final transient Capabilities capabilities;
+	private final transient String description;
+
+	/**
+	 * 
+	 * @param name       the filename. This is not a {@link PartyId}.
+	 * @param partyclass the class of the party.
+	 * @throws ClassNotFoundException if unknown partyclass
+	 */
+	public AvailableJavaParty(String name, Class<? extends Party> partyclass)
+			throws ClassNotFoundException {
+		this.name = name;
+		this.partyclass = partyclass;
+
+		Party party;
+		try {
+			party = partyclass.newInstance();
+		} catch (Throwable e) {
+			throw new ClassNotFoundException(
+					"Could not instantiate " + partyclass, e);
+		}
+		capabilities = party.getCapabilities();
+		description = party.getDescription();
+
+	}
+
+	@Override
+	public String getID() {
+		return name;
+	}
+
+	@Override
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * 
+	 * @return cached copy of what was received from a call to
+	 *         {@link Party#getDescription()}.
+	 */
+	@Override
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * 
+	 * @return cached copy of what was received from a call to
+	 *         {@link AvailableParty#getCapabilities()}
+	 */
+	@Override
+	public Capabilities getCapabilities() {
+		return capabilities;
+	}
+
+	@Override
+	public Party getInstance() throws InstantiationFailedException {
+		try {
+			return partyclass.newInstance();
+		} catch (Exception e) {
+			throw new InstantiationFailedException(
+					"Failed to create instance of party " + this, e);
+		}
+	}
+
+	@Override
+	public void free() {
+		// FAIK we can not unload the class or free resources.
+		// it would be done automatically if our classloader
+		// is garbage collected.
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((name == null) ? 0 : name.hashCode());
+		result = prime * result
+				+ ((partyclass == null) ? 0 : partyclass.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		AvailableJavaParty other = (AvailableJavaParty) obj;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		if (partyclass == null) {
+			if (other.partyclass != null)
+				return false;
+		} else if (!partyclass.equals(other.partyclass))
+			return false;
+		return true;
+	}
+
+	@Override
+	public String toString() {
+		return name + " (" + partyclass + ")";
+	}
+
+}
Index: src/main/java/geniusweb/partiesserver/repository/AvailablePartiesRepo.java
===================================================================
--- src/main/java/geniusweb/partiesserver/repository/AvailablePartiesRepo.java	(revision 30)
+++ src/main/java/geniusweb/partiesserver/repository/AvailablePartiesRepo.java	(revision 31)
@@ -43,6 +43,10 @@
 	@Override
 	public void remove(String id) {
-		availableParties.remove(id);
-		notifyListeners(id);
+		AvailableParty available = availableParties.get(id);
+		if (available != null) {
+			availableParties.remove(id);
+			available.free();
+			notifyListeners(id);
+		}
 	}
 
Index: src/main/java/geniusweb/partiesserver/repository/AvailableParty.java
===================================================================
--- src/main/java/geniusweb/partiesserver/repository/AvailableParty.java	(revision 30)
+++ src/main/java/geniusweb/partiesserver/repository/AvailableParty.java	(revision 31)
@@ -1,51 +1,19 @@
 package geniusweb.partiesserver.repository;
 
-import geniusweb.actions.PartyId;
 import geniusweb.party.Capabilities;
 import geniusweb.party.Party;
 import tudelft.utilities.repository.RepoElement;
 
-public class AvailableParty implements RepoElement<String> {
-
-	private final Class<? extends Party> partyclass;
-	private final String name;
-	private final transient Capabilities capabilities;
-	private final transient String description;
+/**
+ * An interface to an approved and ready to run party. To make a party
+ * available, resources may have to be allocated.
+ */
+public interface AvailableParty extends RepoElement<String> {
 
 	/**
 	 * 
-	 * @param name       the filename. This is not a {@link PartyId}.
-	 * @param partyclass the class of the party.
-	 * @throws ClassNotFoundException if unknown partyclass
+	 * @return the (file) name of the available party
 	 */
-	public AvailableParty(String name, Class<? extends Party> partyclass)
-			throws ClassNotFoundException {
-		this.name = name;
-		this.partyclass = partyclass;
-
-		Party party;
-		try {
-			party = partyclass.newInstance();
-		} catch (Throwable e) {
-			throw new ClassNotFoundException(
-					"Could not instantiate " + partyclass, e);
-		}
-		capabilities = party.getCapabilities();
-		description = party.getDescription();
-
-	}
-
-	@Override
-	public String getID() {
-		return name;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public Class<? extends Party> getPartyClass() {
-		return partyclass;
-	}
+	String getName();
 
 	/**
@@ -54,7 +22,5 @@
 	 *         {@link Party#getDescription()}.
 	 */
-	public String getDescription() {
-		return description;
-	}
+	String getDescription();
 
 	/**
@@ -63,44 +29,23 @@
 	 *         {@link AvailableParty#getCapabilities()}
 	 */
-	public Capabilities getCapabilities() {
-		return capabilities;
-	}
+	Capabilities getCapabilities();
 
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((name == null) ? 0 : name.hashCode());
-		result = prime * result
-				+ ((partyclass == null) ? 0 : partyclass.hashCode());
-		return result;
-	}
+	/**
+	 * 
+	 * @return a link to a Party. Notice, Party may be a intermediary,
+	 *         redirecting data through remote objects
+	 * @throws InstantiationFailedException if party can not be instantiated
+	 *                                      (this should normally not happen,
+	 *                                      since we test thoroughly before a
+	 *                                      party is announced Available, but
+	 *                                      there might be special cases eg out
+	 *                                      of memory)
+	 */
+	Party getInstance() throws InstantiationFailedException;
 
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		AvailableParty other = (AvailableParty) obj;
-		if (name == null) {
-			if (other.name != null)
-				return false;
-		} else if (!name.equals(other.name))
-			return false;
-		if (partyclass == null) {
-			if (other.partyclass != null)
-				return false;
-		} else if (!partyclass.equals(other.partyclass))
-			return false;
-		return true;
-	}
-
-	@Override
-	public String toString() {
-		return name + " (" + partyclass + ")";
-	}
-
+	/**
+	 * Free resources associated with this . After this call, the AvailableParty
+	 * becomes invalid and should be disposed.
+	 */
+	void free();
 }
Index: src/main/java/geniusweb/partiesserver/repository/InstantiationFailedException.java
===================================================================
--- src/main/java/geniusweb/partiesserver/repository/InstantiationFailedException.java	(revision 31)
+++ src/main/java/geniusweb/partiesserver/repository/InstantiationFailedException.java	(revision 31)
@@ -0,0 +1,15 @@
+package geniusweb.partiesserver.repository;
+
+/**
+ * 
+ * Thrown if party can not be instantiated. This should normally not happen,
+ * since we test thoroughly before a party is announced Available, but there
+ * might be special cases eg out of memory *
+ */
+public class InstantiationFailedException extends Exception {
+	private static final long serialVersionUID = -8971815685377471348L;
+
+	public InstantiationFailedException(String msg, Throwable e) {
+		super(msg, e);
+	}
+}
Index: src/main/java/geniusweb/partiesserver/repository/RunningParty.java
===================================================================
--- src/main/java/geniusweb/partiesserver/repository/RunningParty.java	(revision 30)
+++ src/main/java/geniusweb/partiesserver/repository/RunningParty.java	(revision 31)
@@ -17,6 +17,7 @@
 
 /**
- * Class that contains a running party. Adds a start/end times and generates
- * party ID. Also stores original filename of the party.
+ * Contains a running party and additional info about it like time constraints
+ * and connections. Adds a start/end times and generates party ID. Also stores
+ * original filename of the party.
  * 
  * This object can not be deserialized here because running parties have to be
@@ -79,23 +80,15 @@
 	 *                       negotiation
 	 * @return a new RunningParty being an instance of availableparty
-	 * @throws IllegalAccessException if the class or its nullary constructor is
-	 *                                not accessible.
-	 * 
-	 * @throws InstantiationException if this Class represents an abstract
-	 *                                class, an interface, an array class, a
-	 *                                primitive type, or void; or if the class
-	 *                                has no nullary constructor; or if the
-	 *                                instantiation fails for some other reason.
+	 * @throws InstantiationFailedException if class can not be instantiated
 	 * 
 	 */
 	public static RunningParty create(AvailableParty availableparty,
-			long maxlifetimems)
-			throws InstantiationException, IllegalAccessException {
+			long maxlifetimems) throws InstantiationFailedException {
 		if (availableparty == null) {
 			throw new IllegalArgumentException(
 					"availableparty must not be null");
 		}
-		return create(availableparty.getPartyClass().newInstance(),
-				availableparty.getName(), maxlifetimems);
+		return create(availableparty.getInstance(), availableparty.getName(),
+				maxlifetimems);
 	}
 
@@ -213,6 +206,6 @@
 
 	/**
-	 * You must have called {@link #withConnection(PartySocket)} before calling
-	 * this.
+	 * Pass {@link Inform} into the running party. You must have called
+	 * {@link #withConnection(PartySocket)} before calling this.
 	 * 
 	 * @param info the {@link Inform} to be sent to the {@link #connection}
Index: src/main/java/geniusweb/partiesserver/websocket/ActiveThreads.java
===================================================================
--- src/main/java/geniusweb/partiesserver/websocket/ActiveThreads.java	(revision 30)
+++ src/main/java/geniusweb/partiesserver/websocket/ActiveThreads.java	(revision 31)
@@ -64,5 +64,5 @@
 						"Killed thread with stack trace\n" + stacktrace);
 			} catch (ThreadDeath e) {
-				System.out.println("Noticed thread already was stopped.");
+				log.log(Level.INFO, "Noticed thread already was stopped.");
 			}
 		}
Index: src/main/java/geniusweb/partiesserver/websocket/PartiesListSocket.java
===================================================================
--- src/main/java/geniusweb/partiesserver/websocket/PartiesListSocket.java	(revision 30)
+++ src/main/java/geniusweb/partiesserver/websocket/PartiesListSocket.java	(revision 31)
@@ -52,4 +52,6 @@
 
 	public PartiesListSocket(Reporter reporter) {
+		if (reporter == null)
+			throw new IllegalArgumentException("reporter must be not null");
 		this.log = reporter;
 	}
@@ -78,5 +80,5 @@
 	 */
 	private void sendUpdatedParties() {
-		System.out.println("sending updated parties list1");
+		log.log(Level.INFO, "sending updated parties list1");
 		String ip = DEFAULT_ADDRESS; // default if something fails
 		try {
Index: src/main/java/geniusweb/partiesserver/websocket/PartySocket.java
===================================================================
--- src/main/java/geniusweb/partiesserver/websocket/PartySocket.java	(revision 30)
+++ src/main/java/geniusweb/partiesserver/websocket/PartySocket.java	(revision 31)
@@ -34,7 +34,9 @@
 
 /**
- * Returns a websocket that communicates with the {@link RunningParty}. We close
- * the socket when we detect the party is gone (eg, due to a bug in the party or
- * a time-out). If the socket breaks, we close the party as it becomes isolated.
+ * Returns a websocket that communicates with the {@link RunningParty}. The
+ * websocket is initiated/called/requested by an external party, typicall hte
+ * protocol running on another server. We close the socket when we detect the
+ * party is gone (eg, due to a bug in the party or a time-out). If the socket
+ * breaks, we close the party as it becomes isolated.
  */
 @ServerEndpoint("/party/{party}")
@@ -228,4 +230,10 @@
 	@Override
 	public void send(Action action) throws IOException {
+		if (action == null) {
+			log.log(Level.INFO, "null action received. Closing websocket");
+			// signals that party closed the stream
+			close();
+			return;
+		}
 		log.log(Level.FINE, "Action " + partyID + ": " + action);
 		outstream.send(Jackson.instance().writeValueAsString(action));
Index: src/main/java/geniusweb/partiesserver/websocket/SendBuffer.java
===================================================================
--- src/main/java/geniusweb/partiesserver/websocket/SendBuffer.java	(revision 30)
+++ src/main/java/geniusweb/partiesserver/websocket/SendBuffer.java	(revision 31)
@@ -21,6 +21,11 @@
 
 	private final Basic remote;
+	/**
+	 * Buffer contains jackson-serialized objects, so can be "null" or "" but
+	 * not null. "" (empty string) indicates buffer should be closed and
+	 * terminated.
+	 */
 	private final LinkedBlockingQueue<String> fifo = new LinkedBlockingQueue<String>();
-	private final Thread thread;
+	private Thread thread;
 	private final Reporter log;
 
@@ -32,7 +37,11 @@
 			@Override
 			public void run() {
+				String txt = "-";
 				try {
 					while (true) {
-						remote.sendText(fifo.take());
+						txt = fifo.take();
+						if (txt.isEmpty())
+							break;
+						remote.sendText(txt);
 					}
 				} catch (InterruptedException e) {
@@ -41,11 +50,18 @@
 							"sendbuffer is interrupted, assuming the party died.");
 				} catch (Exception e) {
-					logger.log(Level.SEVERE, "Failed to write to stream", e);
+					logger.log(Level.SEVERE,
+							"Failed to write '" + txt + "' to stream", e);
 				}
+				log.log(Level.INFO, "SendBuffer is closed.");
 			}
-		});
+		}, "SendBuffer");
 		thread.start();
 	}
 
+	/**
+	 * 
+	 * @param text text to be sent. Typically/never null as this already is a
+	 *             jackson-serialized string.
+	 */
 	public void send(String text) {
 		try {
@@ -61,22 +77,29 @@
 	 * Stop the que, disable, terminate threads
 	 */
-	public void stop() {
-		if (!fifo.isEmpty()) {
-			try {
-				log.log(Level.FINE, "Allowing short time to send remaining "
-						+ fifo.size() + "messages");
-				thread.sleep(1000);
-			} catch (InterruptedException e) {
-				log.log(Level.FINE,
-						"Waiting was interrupted, final messages have been deleted");
-			}
-		}
-		thread.interrupt();
+	public synchronized void stop() {
 		try {
-			thread.join(400);
+			stop1();
 		} catch (InterruptedException e) {
 			log.log(Level.WARNING,
-					"thread termination was interrupted, unsure about thread state");
+					"Queue termination was interrupted, unsure about thread state");
 		}
+		thread = null;
+	}
+
+	private void stop1() throws InterruptedException {
+		if (thread == null)
+			return;
+
+		fifo.put("");
+		Thread.sleep(100);
+		if (fifo.isEmpty())
+			return;
+		log.log(Level.FINE, "Allowing short time to send remaining "
+				+ fifo.size() + "messages");
+		Thread.sleep(1000);
+		if (fifo.isEmpty())
+			return;
+		log.log(Level.WARNING, "Fifo is still not fihished. Requesting kill");
+		thread.interrupt();
 	}
 
