Index: java/main/pom.xml
===================================================================
--- java/main/pom.xml	(revision 101)
+++ java/main/pom.xml	(revision 102)
@@ -57,4 +57,9 @@
 		</dependency>
 		<dependency>
+			<groupId>commons-lang</groupId>
+			<artifactId>commons-lang</artifactId>
+			<version>2.3</version>
+		</dependency>
+		<dependency>
 			<groupId>java3d</groupId>
 			<artifactId>j3d-core</artifactId>
@@ -81,4 +86,5 @@
 			<artifactId>fest-assert</artifactId>
 			<version>1.4</version>
+			<scope>test</scope>
 		</dependency>
 		<dependency>
@@ -86,4 +92,5 @@
 			<artifactId>fest-swing-testng</artifactId>
 			<version>1.2.1</version>
+			<scope>test</scope>
 		</dependency>
 
Index: java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java	(revision 102)
@@ -132,5 +132,4 @@
 
 	public void send(ProtocolRequest request, ClientSideResponseFuture callback) {
-		//TODO RunAt
 		sendImplementation(request, AtOnceDispatcher.getInstance(), callback);
 	}
@@ -466,5 +465,5 @@
 
 		final String finalEventPath = eventPath;
-				//TODO add arguments to the exception
+		//TODO add arguments to the exception
 		send(new CallRequest().procedure("remove").path(eventPath), dispatcher, new ClientSideResponseFuture(future) {
 
Index: java/main/src/main/java/com/framsticks/communication/Connection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 102)
@@ -18,5 +18,4 @@
 import java.io.PrintWriter;
 import java.net.Socket;
-import java.net.SocketTimeoutException;
 import java.util.Collection;
 import java.util.HashSet;
@@ -87,8 +86,4 @@
 	public Connection setAddress(String address) {
 		return setAddress(new Address(address));
-	}
-
-	public synchronized boolean isConnected() {
-		return socket != null && socket.isConnected();
 	}
 
@@ -131,10 +126,7 @@
 
 				readChars = 0;
-				while (readChars == 0) {
-					try {
-						readChars = input.read(readBuffer);
-					} catch (SocketTimeoutException ignored) {
-						//timeout - continue
-					}
+				readChars = input.read(readBuffer);
+				if (readChars < 0) {
+					throw new SocketClosedException().msg("socket is closed");
 				}
 				iterator = 0;
@@ -143,5 +135,6 @@
 			throw new InterruptedException();
 		} catch (Exception e) {
-			throw new FramsticksException().msg("failed to read line").cause(e);
+			log.debug("failed to read line (closing): {}", e.getMessage());
+			throw new SocketClosedException().msg("failed to read line").cause(e);
 		}
 	}
@@ -162,9 +155,15 @@
 	protected abstract void processNextInputBatch();
 
+
 	protected final void processInputBatchesUntilClosed() {
-		while (isRunning() && isConnected()) {
+		while (isRunning() && !socket.isClosed()) {
 			try {
 				processNextInputBatch();
+			} catch (SocketClosedException e) {
+				log.log(isRunning() ? Level.ERROR : Level.DEBUG, "socket is closing: {}", e.getShortMessage(new StringBuilder()));
+				// log.log(isRunning() ? Level.ERROR : Level.DEBUG, "caught exception: ", e);
+				break;
 			} catch (FramsticksException e) {
+				log.debug("{} caught exception in receiver thread {}", this, e.getMessage());
 				handle(e);
 			} catch (Exception e) {
@@ -173,4 +172,5 @@
 			}
 		}
+		log.debug("{} finished processing input", this);
 	}
 
@@ -227,5 +227,5 @@
 		Dispatching.use(threads, this);
 
-		senderThread.dispatch(new RunAt<Connection>(ThrowExceptionHandler.getInstance()) {
+		senderThread.dispatch(new RunAt<Connection>(this) {
 			@Override
 			protected void runAt() {
@@ -238,10 +238,10 @@
 		});
 
-		receiverThread.dispatch(new RunAt<Connection>(ThrowExceptionHandler.getInstance()) {
+		receiverThread.dispatch(new RunAt<Connection>(this) {
 			@Override
 			protected void runAt() {
 				receiverThreadRoutine();
 				interruptJoinable();
-				finishJoinable();
+				// finishJoinable();
 			}
 		});
@@ -260,10 +260,10 @@
 
 	protected static void startClientConnection(Connection connection) {
-		while (connection.isRunning() && !connection.isConnected()) {
+		while (connection.isRunning() && connection.socket == null) {
 			log.debug("connecting to {}", connection.address);
 			try {
 				connection.socket = new Socket(connection.getAddressObject().getHostName(), connection.getAddressObject().getPort());
 			} catch (IOException e) {
-				log.info("{} failed to connect (retrying): ", connection, e);
+				log.warn("{} failed to connect (retrying): {}", connection, e.getMessage());
 				Dispatching.sleep(0.5);
 			}
@@ -272,5 +272,5 @@
 		log.debug("{} connected", connection);
 		try {
-			connection.socket.setSoTimeout(500);
+			// connection.socket.setSoTimeout(500);
 			connection.setupStreams();
 		} catch (Exception e) {
@@ -319,4 +319,5 @@
 	@Override
 	public void handle(FramsticksException exception) {
+		log.debug("{} handling {}", this, exception.getMessage());
 		exceptionHandler.handle(exception);
 	}
@@ -358,3 +359,7 @@
 	}
 
+	public synchronized boolean isConnected() {
+		return socket != null && socket.isConnected();
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java	(revision 102)
@@ -32,7 +32,4 @@
 
 
-	protected void processNextInputBatch() {
-		processNextRequest();
-	}
 
 	@Override
@@ -92,5 +89,5 @@
 
 
-	protected void processNextRequest() {
+	protected void processNextInputBatch() {
 		final Holder<Integer> id = new Holder<>();
 		final String line = getLine();
@@ -106,5 +103,4 @@
 			}
 
-			//TODO what to do here?
 			handleRequest(request, new ServerSideResponseFuture() {
 				@Override
Index: java/main/src/main/java/com/framsticks/communication/SocketClosedException.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/SocketClosedException.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/communication/SocketClosedException.java	(revision 102)
@@ -0,0 +1,8 @@
+package com.framsticks.communication;
+
+import com.framsticks.util.FramsticksException;
+
+@SuppressWarnings("serial")
+public class SocketClosedException extends FramsticksException {
+
+}
Index: java/main/src/main/java/com/framsticks/core/AbstractTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/AbstractTree.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/core/AbstractTree.java	(revision 102)
@@ -34,5 +34,4 @@
 import com.framsticks.util.dispatching.JoinableState;
 import com.framsticks.util.dispatching.RunAt;
-import com.framsticks.util.dispatching.Thread;
 import com.framsticks.util.dispatching.ThrowExceptionHandler;
 import com.framsticks.util.lang.Pair;
@@ -42,5 +41,5 @@
  */
 @FramsClassAnnotation
-public abstract class AbstractTree extends AbstractJoinable implements Dispatcher<Tree>, Tree, JoinableParent, NeedFileAcceptor {
+public abstract class AbstractTree extends AbstractJoinable implements Tree, JoinableParent, NeedFileAcceptor {
 
 	private static final Logger log = LogManager.getLogger(AbstractTree.class);
@@ -49,5 +48,5 @@
 	private ExceptionResultHandler handler = ThrowExceptionHandler.getInstance();
 
-	protected final BufferedDispatcher<Tree> bufferedDispatcher = new BufferedDispatcher<>();
+	protected final BufferedDispatcher<Tree> bufferedDispatcher = new BufferedDispatcher<>(this);
 
 	protected final PriorityQueue<Pair<Integer, NeedFileAcceptor>> needFileAcceptors = new PriorityQueue<>(32, new Comparator<Pair<Integer, NeedFileAcceptor>>() {
@@ -77,5 +76,5 @@
 	public void assignRootObject(Object object) {
 		if (root == null) {
-			throw new FramsticksException().msg("root is has no type specified");
+			throw new FramsticksException().msg("root has no type specified");
 		}
 		if (root.getObject() != null) {
@@ -89,5 +88,5 @@
 	public @Nonnull Node getAssignedRoot() {
 		if (root == null) {
-			throw new FramsticksException().msg("root has no type specified yet");
+			throw new FramsticksException().msg("root has no type specified yet").arg("in", this);
 		}
 		return root;
@@ -173,5 +172,5 @@
 	@Override
 	public Dispatcher<Tree> getDispatcher() {
-		return bufferedDispatcher.getTargetDispatcher();
+		return bufferedDispatcher;
 	}
 
@@ -181,7 +180,4 @@
 	@Override
 	public void setDispatcher(Dispatcher<Tree> dispatcher) {
-		if (bufferedDispatcher.getTargetDispatcher() != null) {
-			throw new FramsticksException().msg("dispatcher is already set").arg("tree", this).arg("dispatcher", bufferedDispatcher.getTargetDispatcher());
-		}
 		bufferedDispatcher.setTargetDispatcher(dispatcher);
 	}
@@ -213,13 +209,11 @@
 	@Override
 	protected void joinableStart() {
-		if (bufferedDispatcher.getTargetDispatcher() == null) {
-			bufferedDispatcher.setTargetDispatcher(new Thread<Tree>());
-		}
-		Dispatching.use(bufferedDispatcher.getTargetDispatcher(), this);
+		bufferedDispatcher.createThreadIfNeeded();
+		Dispatching.use(bufferedDispatcher, this);
 	}
 
 	@Override
 	protected void joinableInterrupt() {
-		Dispatching.drop(bufferedDispatcher.getTargetDispatcher(), this);
+		Dispatching.drop(bufferedDispatcher, this);
 	}
 
@@ -231,10 +225,10 @@
 	@Override
 	protected void joinableJoin() throws InterruptedException {
-		Dispatching.join(bufferedDispatcher.getTargetDispatcher());
+		Dispatching.join(bufferedDispatcher);
 	}
 
 	@Override
 	public void childChangedState(Joinable joinable, JoinableState state) {
-		if (joinable == bufferedDispatcher.getTargetDispatcher()) {
+		if (joinable == bufferedDispatcher) {
 			proceedToState(state);
 		}
@@ -333,5 +327,5 @@
 					}
 				}
-				throw new FramsticksException().msg("failed to find need file acceptor in tree").arg("tree", AbstractTree.this);
+				throw new FramsticksException().msg("failed to find need file acceptor in tree").arg("tree", AbstractTree.this).arg("needfile", needFile);
 			}
 		});
Index: java/main/src/main/java/com/framsticks/core/ListChange.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/ListChange.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/core/ListChange.java	(revision 102)
@@ -1,3 +1,9 @@
 package com.framsticks.core;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.lang.StringUtils;
 
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -9,15 +15,24 @@
  * @author Piotr Sniegowski
  */
-@FramsClassAnnotation(order = {"type", "pos", "id"})
+@FramsClassAnnotation(order = {"type", "pos", "id", "hint"})
 public class ListChange {
 
+	public static enum Action {
+		Add,
+		Remove,
+		Modify
+	}
 
-	/**
-	 * @param action
-	 */
-	public ListChange(Action action, Integer position, String identifier) {
+
+	public ListChange(Action action, Integer position, String identifier, Object... hints) {
 		this.action = action;
 		this.position = position;
 		this.identifier = identifier;
+		if (hints.length != 0) {
+			this.hints = new TreeSet<>();
+			for (Object h : hints) {
+				this.hints.add(h.toString());
+			}
+		}
 	}
 
@@ -40,22 +55,12 @@
 	}
 
-	public static enum Action {
-		Add,
-		Remove,
-		Modify
-		// Add(0),
-		// Remove(1),
-		// Modify(2);
 
-		// public final int value;
+	public boolean hasHint(String hint) {
+		if (hints == null) {
+			return false;
+		}
+		return hints.contains(hint);
+	}
 
-		// /**
-		//  * @param value
-		//  */
-		// Action(int value) {
-		//	this.value = value;
-		// }
-
-	}
 
 	public Action action = Action.Add;
@@ -64,4 +69,21 @@
 	@ParamAnnotation(id = "id")
 	public String identifier;
+
+	protected Set<String> hints;
+
+	@ParamAnnotation
+	public String getHints() {
+		return StringUtils.join(hints, ",");
+	}
+
+	@ParamAnnotation
+	public void setHints(String hints) {
+		if (!Strings.notEmpty(hints)) {
+			this.hints = null;
+			return;
+		}
+		this.hints = new TreeSet<>();
+		this.hints.addAll(Arrays.asList(StringUtils.split(hints, ",")));
+	}
 
 	@ParamAnnotation
@@ -79,5 +101,10 @@
 	@Override
 	public String toString() {
-		return action + " " + identifier + " " + position;
+		StringBuilder b = new StringBuilder();
+		b.append(action).append(" ").append(identifier).append(" ").append(position);
+		if (hints != null && !hints.isEmpty()) {
+			b.append(" ").append(getHints());
+		}
+		return b.toString();
 	}
 
@@ -86,5 +113,5 @@
 		if (object instanceof ListChange) {
 			ListChange r = (ListChange) object;
-			return Misc.equals(action, r.action) && Misc.equals(position, r.position) && Misc.equals(identifier, r.identifier);
+			return Misc.equals(action, r.action) && Misc.equals(position, r.position) && Misc.equals(identifier, r.identifier) && Misc.equals(hints, r.hints);
 		}
 		return false;
Index: java/main/src/main/java/com/framsticks/core/LocalTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/LocalTree.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/core/LocalTree.java	(revision 102)
@@ -15,4 +15,6 @@
 import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.DispatcherSetable;
 import com.framsticks.util.dispatching.Dispatching;
 import com.framsticks.util.dispatching.Future;
@@ -33,7 +35,8 @@
 	public LocalTree() {
 		super();
-
+		bufferedDispatcher.setBuffer(false);
 	}
 
+	@SuppressWarnings({ "rawtypes", "unchecked" })
 	@AutoAppendAnnotation
 	public void setRootObject(Object object) {
@@ -49,15 +52,20 @@
 			joinableRootObject = (Joinable) object;
 		}
+		if (object instanceof DispatcherSetable) {
+			DispatcherSetable<?> setable = (DispatcherSetable<?>) object;
+			setable.setDispatcher((Dispatcher) this);
+		}
 	}
 
 	public Object getRootObject() {
-		return getAssignedRoot().getObject();
+		Object result = getAssignedRoot().getObject();
+		if (result == null) {
+			throw new FramsticksException().msg("object tree is empty").arg("tree", this);
+		}
+		return result;
 	}
 
 	public <T> T getRootObject(Class<T> type) {
 		Object result = getRootObject();
-		if (result == null) {
-			throw new FramsticksException().msg("object tree is empty").arg("tree", this);
-		}
 		if (!type.isInstance(result)) {
 			throw new FramsticksException().msg("object tree holds object of different kind").arg("object", result).arg("requested", type).arg("tree", this);
@@ -181,3 +189,4 @@
 		}
 	}
+
 }
Index: java/main/src/main/java/com/framsticks/core/Tree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Tree.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/core/Tree.java	(revision 102)
@@ -13,9 +13,10 @@
 import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.DispatcherSetable;
 import com.framsticks.util.dispatching.ExceptionResultHandler;
 import com.framsticks.util.dispatching.Future;
 import com.framsticks.util.dispatching.Joinable;
 
-public interface Tree extends Dispatcher<Tree>, Joinable, ExceptionResultHandler {
+public interface Tree extends Dispatcher<Tree>, DispatcherSetable<Tree>, Joinable, ExceptionResultHandler {
 
 	public @Nonnull Node getAssignedRoot();
@@ -54,7 +55,7 @@
 	public ExceptionResultHandler getExceptionHandler();
 
-	public void setDispatcher(Dispatcher<Tree> dispatcher);
+	// public void setDispatcher(Dispatcher<Tree> dispatcher);
 
-	public Dispatcher<Tree> getDispatcher();
+	// public Dispatcher<Tree> getDispatcher();
 
 	public <A> void addListener(Path path, EventParam param, EventListener<A> listener, Class<A> argumentType, Future<Void> future);
Index: java/main/src/main/java/com/framsticks/core/TreeOperations.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/TreeOperations.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/core/TreeOperations.java	(revision 102)
@@ -44,6 +44,5 @@
 	public static final SideNoteKey<Boolean> FETCHED_MARK = SideNoteKey.make(Boolean.class);
 
-	public static @Nonnull
-	FramsClass processFetchedInfo(Tree tree, File file) {
+	public static @Nonnull FramsClass processFetchedInfo(Tree tree, File file) {
 		assert tree.isActive();
 		FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
Index: java/main/src/main/java/com/framsticks/dumping/PrintWriterSink.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/PrintWriterSink.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/dumping/PrintWriterSink.java	(revision 102)
@@ -1,5 +1,5 @@
 package com.framsticks.dumping;
 
-import com.framsticks.params.SinkInterface;
+import com.framsticks.params.Sink;
 
 import java.io.PrintWriter;
@@ -8,5 +8,5 @@
  * @author Piotr Sniegowski
  */
-public class PrintWriterSink implements SinkInterface {
+public class PrintWriterSink implements Sink {
 
     protected final PrintWriter stream;
Index: java/main/src/main/java/com/framsticks/dumping/SaveStream.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 102)
@@ -2,4 +2,5 @@
 
 import static com.framsticks.core.TreeOperations.*;
+import static com.framsticks.params.AccessOperations.*;
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
@@ -8,5 +9,5 @@
 import com.framsticks.params.FramsClass;
 import com.framsticks.params.ListAccess;
-import com.framsticks.params.SinkInterface;
+import com.framsticks.params.Sink;
 import com.framsticks.parsers.Savers;
 import com.framsticks.core.Tree;
@@ -30,5 +31,5 @@
 	private final static Logger log = LogManager.getLogger(SaveStream.class.getName());
 
-	protected final SinkInterface sink;
+	protected final Sink sink;
 	protected final Tree tree;
 	protected final Future<Void> future;
@@ -38,5 +39,5 @@
 	private int dispatched = 0;
 
-	public SaveStream(SinkInterface sink, Tree tree, Path root, Future<Void> future) {
+	public SaveStream(Sink sink, Tree tree, Path root, Future<Void> future) {
 		assert Dispatching.isThreadSafe();
 		this.sink = sink;
@@ -83,5 +84,5 @@
 				sink.print("file").breakLine();
 				//stream.print("#" + access.getSelected().getClass().getCanonicalName() + "\n");
-				access.save(sink);
+				save(access, sink);
 				sink.print("eof").breakLine();
 				sink.print("ok").breakLine();
Index: java/main/src/main/java/com/framsticks/experiment/AbstractExperimentLogic.java
===================================================================
--- java/main/src/main/java/com/framsticks/experiment/AbstractExperimentLogic.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/experiment/AbstractExperimentLogic.java	(revision 102)
@@ -0,0 +1,21 @@
+package com.framsticks.experiment;
+
+public class AbstractExperimentLogic implements ExperimentLogic {
+
+	protected final Experiment experiment;
+
+	/**
+	 * @param experiment
+	 */
+	public AbstractExperimentLogic(Experiment experiment) {
+		this.experiment = experiment;
+	}
+
+	/**
+	 * @return the experiment
+	 */
+	public Experiment getExperiment() {
+		return experiment;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/experiment/Experiment.java
===================================================================
--- java/main/src/main/java/com/framsticks/experiment/Experiment.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/experiment/Experiment.java	(revision 102)
@@ -2,17 +2,74 @@
 
 import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.core.ListChange;
 import com.framsticks.params.EventListener;
+import com.framsticks.params.ParamFlags;
 import com.framsticks.params.SimpleUniqueList;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.remote.RemoteTree;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.AbstractJoinable;
+import com.framsticks.util.dispatching.BufferedDispatcher;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.DispatcherSetable;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.Joinable;
 import com.framsticks.util.dispatching.JoinableCollection;
+import com.framsticks.util.dispatching.JoinableParent;
+import com.framsticks.util.dispatching.JoinableState;
+import com.framsticks.util.dispatching.RunAt;
 
 @FramsClassAnnotation
-public class Experiment extends JoinableCollection<Simulator> {
+public class Experiment extends AbstractJoinable implements Dispatcher<Experiment>, DispatcherSetable<Experiment>, JoinableParent, ExceptionResultHandler {
+	private static final Logger log = LogManager.getLogger(Experiment.class);
+
+	protected final JoinableCollection<Simulator> simulatorAsJoinables = new JoinableCollection<Simulator>().setObservableName("simulators");
+
+	protected final JoinableCollection<RemoteTree> simulatorCandidates = new JoinableCollection<RemoteTree>().setObservableName("candidates");
 
 	protected final SimpleUniqueList<Simulator> simulators = new SimpleUniqueList<>(Simulator.class, 's');
+
+	protected final SimpleUniqueList<Simulator> oldSimulators = new SimpleUniqueList<>(Simulator.class, 's');
+
+	protected final BufferedDispatcher<Experiment> bufferedDispatcher = new BufferedDispatcher<>(this);
+
+	protected String expdef;
+
+	/**
+	 *
+	 */
+	public Experiment() {
+		super();
+		bufferedDispatcher.setBuffer(false);
+
+		Dispatching.dispatchLog(this, log, Level.DEBUG, "first task");
+
+
+		simulators.addListener(new EventListener<ListChange>() {
+			@Override
+			public void action(ListChange argument) {
+				if (argument.getAction() == ListChange.Action.Add) {
+					simulators.fireChildrenChange(argument, ListChange.Action.Modify, "ready");
+				}
+			}
+		});
+
+	}
+
+	/**
+	 * @return the simulatorCandidates
+	 */
+	public JoinableCollection<RemoteTree> getSimulatorCandidates() {
+		return simulatorCandidates;
+	}
 
 	@ParamAnnotation
@@ -21,4 +78,41 @@
 	}
 
+	@ParamAnnotation(id = "old_simulators")
+	public Map<String, Simulator> getOldSimulators() {
+		return oldSimulators.getView();
+	}
+
+	/**
+	 * @return the dispatcher
+	 */
+	@Override
+	public Dispatcher<Experiment> getDispatcher() {
+		return bufferedDispatcher;
+	}
+
+	/**
+	 * @param dispatcher the dispatcher to set
+	 */
+	@Override
+	public void setDispatcher(Dispatcher<Experiment> dispatcher) {
+		bufferedDispatcher.setTargetDispatcher(dispatcher);
+	}
+
+	/**
+	 * @return the expdef
+	 */
+	@ParamAnnotation(flags = ParamFlags.USERREADONLY)
+	public String getExpdef() {
+		return expdef;
+	}
+
+	/**
+	 * @param expdef the expdef to set
+	 */
+	@ParamAnnotation
+	public void setExpdef(String expdef) {
+		this.expdef = expdef;
+	}
+
 	@ParamAnnotation(id = "simulators_changed")
 	public void addSimulatorsListener(EventListener<ListChange> listener) {
@@ -34,4 +128,91 @@
 	public void addSimulator(Simulator simulator) {
 		simulators.add(simulator);
-	}
+		simulatorAsJoinables.add(simulator);
+
+
+
+
+
+	}
+
+	protected void removeSimulator(Simulator simulator) {
+		simulatorAsJoinables.remove(simulator);
+		simulators.remove(simulator);
+		oldSimulators.add(simulator);
+	}
+
+	@ParamAnnotation(id = "old_simulators_changed")
+	public void addOldSimulatorsListener(EventListener<ListChange> listener) {
+		oldSimulators.addListener(listener);
+	}
+
+	@ParamAnnotation(id = "old_simulators_changed")
+	public void removeOldSimulatorsListener(EventListener<ListChange> listener) {
+		oldSimulators.removeListener(listener);
+	}
+
+	@Override
+	public String getName() {
+		return "experiment";
+	}
+
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		proceedToState(state);
+	}
+
+	@Override
+	protected void joinableStart() {
+		bufferedDispatcher.createThreadIfNeeded();
+		Dispatching.use(bufferedDispatcher, this);
+
+		Dispatching.use(simulatorAsJoinables, this);
+		Dispatching.use(simulatorCandidates, this);
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+
+		Dispatching.drop(simulatorAsJoinables, this);
+		Dispatching.drop(simulatorCandidates, this);
+
+		finishJoinable();
+	}
+
+	@Override
+	protected void joinableFinish() {
+		log.debug("finishing experiment {}", this);
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.drop(bufferedDispatcher, this);
+
+		Dispatching.join(simulatorAsJoinables);
+		Dispatching.join(simulatorCandidates);
+		Dispatching.join(bufferedDispatcher.getTargetDispatcher());
+	}
+
+	@Override
+	public void handle(FramsticksException exception) {
+		log.error("caught exception: ", exception);
+	}
+
+	@Override
+	public boolean isActive() {
+		return bufferedDispatcher.isActive();
+	}
+
+	@Override
+	public void dispatch(RunAt<? extends Experiment> runnable) {
+		bufferedDispatcher.dispatch(runnable);
+	}
+
+	@ParamAnnotation(paramType = ProcedureParam.class)
+	public void connectToSimulator(String address) {
+		SimulatorConnector connector = new SimulatorConnector();
+		connector.setAddress(address);
+		connector.attachTo(this);
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/experiment/ExperimentLogic.java
===================================================================
--- java/main/src/main/java/com/framsticks/experiment/ExperimentLogic.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/experiment/ExperimentLogic.java	(revision 102)
@@ -0,0 +1,5 @@
+package com.framsticks.experiment;
+
+public interface ExperimentLogic {
+
+}
Index: java/main/src/main/java/com/framsticks/experiment/NetLoadSaveLogic.java
===================================================================
--- java/main/src/main/java/com/framsticks/experiment/NetLoadSaveLogic.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/experiment/NetLoadSaveLogic.java	(revision 102)
@@ -0,0 +1,76 @@
+package com.framsticks.experiment;
+
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.communication.File;
+import com.framsticks.core.ListChange;
+import com.framsticks.params.EventListener;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
+
+@FramsClassAnnotation
+public abstract class NetLoadSaveLogic extends AbstractExperimentLogic {
+	private static final Logger log = LogManager.getLogger(NetLoadSaveLogic.class);
+
+
+	protected String option = "an option";
+
+	/**
+	 * @param experiment
+	 */
+	public NetLoadSaveLogic(Experiment parentExperiment) {
+		super(parentExperiment);
+
+		experiment.addSimulatorsListener(new EventListener<ListChange>() {
+
+			@Override
+			public void action(ListChange argument) {
+				assert experiment.isActive();
+
+				if (argument.hasHint("ready")) {
+					final Simulator simulator = experiment.getSimulators().get(argument.getIdentifier());
+					log.debug("simulator is ready: {}", simulator);
+
+					netload(simulator, new FutureHandler<File>(simulator) {
+
+						@Override
+						protected void result(final File file) {
+							simulator.uploadNet(file, new FutureHandler<Object>(this) {
+
+								@Override
+								protected void result(Object result) {
+									log.debug("netload of {} done", file);
+								}
+							});
+						}
+					});
+				}
+			}
+		});
+	}
+
+	public abstract void netload(Simulator simulator, Future<File> net);
+
+	public abstract void netsave(Simulator simulator, File net);
+
+	/**
+	 * @return the option
+	 */
+	@ParamAnnotation
+	public String getOption() {
+		return option;
+	}
+
+	/**
+	 * @param option the option to set
+	 */
+	@ParamAnnotation
+	public void setOption(String option) {
+		this.option = option;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/experiment/Simulator.java
===================================================================
--- java/main/src/main/java/com/framsticks/experiment/Simulator.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/experiment/Simulator.java	(revision 102)
@@ -1,35 +1,80 @@
 package com.framsticks.experiment;
 
-import com.framsticks.params.ParamFlags;
+import com.framsticks.communication.File;
+import com.framsticks.communication.queries.NeedFile;
+import com.framsticks.communication.queries.NeedFileAcceptor;
+import com.framsticks.core.Path;
+import com.framsticks.core.Tree;
+import com.framsticks.core.ValueChange;
+import com.framsticks.params.EventListener;
+import com.framsticks.params.FramsClass;
 import com.framsticks.params.UniqueObject;
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.params.types.EventParam;
 import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.remote.RemoteTree;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.dispatching.AbstractJoinable;
+import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
 import com.framsticks.util.dispatching.Joinable;
 import com.framsticks.util.dispatching.JoinableParent;
 import com.framsticks.util.dispatching.JoinableState;
+import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+import com.framsticks.util.lang.Holder;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import static com.framsticks.core.TreeOperations.*;
 
 @FramsClassAnnotation
-public class Simulator extends AbstractJoinable implements JoinableParent, UniqueObject {
+public final class Simulator extends AbstractJoinable implements Dispatcher<Simulator>, JoinableParent, UniqueObject, ExceptionResultHandler {
+
+	private static final Logger log = LogManager.getLogger(Simulator.class);
+
 	protected String uid;
 
-	protected final RemoteTree remoteTree = new RemoteTree();
+	protected final RemoteTree remoteTree;
+	protected final Path simulatorPath;
+	protected final FramsClass simulatorClass;
+	protected final Experiment experiment;
+	protected final EventListener<ValueChange> runningListener;
 
 	/**
 	 *
 	 */
-	public Simulator() {
+	public Simulator(Experiment experiment, RemoteTree remoteTree, Path simulatorPath) {
 		super();
-	}
-
-	@ParamAnnotation
-	public void setAddress(String address) {
-		remoteTree.setAddress(address);
-	}
-
-	@ParamAnnotation(flags = ParamFlags.USERREADONLY)
+		this.remoteTree = remoteTree;
+		this.simulatorPath = simulatorPath.assureResolved();
+		this.experiment = experiment;
+		this.simulatorClass = getFramsClass(simulatorPath);
+
+		assert remoteTree.isActive();
+		assert experiment.isActive();
+
+		log.debug("simulator ready {}", this);
+
+		runningListener = new EventListener<ValueChange>() {
+			@Override
+			public void action(ValueChange argument) {
+				log.debug("running state of {} changed: {}", this, argument);
+			}
+		};
+
+		addListener(simulatorPath, simulatorClass.getParamEntry("running_changed", EventParam.class), runningListener, ValueChange.class, new FutureHandler<Void>(this) {
+			@Override
+			protected void result(Void result) {
+				log.debug("running listener for {} registered", this);
+			}
+		});
+	}
+
+	@ParamAnnotation
 	public String getAddress() {
 		return remoteTree.getAddress();
@@ -39,6 +84,5 @@
 	@ParamAnnotation
 	public String getName() {
-
-		return "simulator " + uid + " " + getAddress();
+		return getAddress();
 	}
 
@@ -62,8 +106,21 @@
 	}
 
+	/**
+	 * @return the simulatorPath
+	 */
+	public Path getSimulatorPath() {
+		return simulatorPath;
+	}
+
+	/**
+	 * @return the simulatorClass
+	 */
+	public FramsClass getSimulatorClass() {
+		return simulatorClass;
+	}
+
 	@Override
 	protected void joinableStart() {
 		Dispatching.use(remoteTree, this);
-
 	}
 
@@ -96,4 +153,12 @@
 	}
 
+	@ParamAnnotation(paramType = ProcedureParam.class)
+	public void abort() {
+		assert isActive();
+		log.debug("explicitly aborting {}", this);
+		experiment.removeSimulator(this);
+		interruptJoinable();
+	}
+
 	@Override
 	public void childChangedState(Joinable joinable, JoinableState state) {
@@ -101,3 +166,62 @@
 	}
 
+	@Override
+	public void handle(FramsticksException exception) {
+		experiment.handle(new FramsticksException().msg("exception caught in simulator").arg("simulator", this).cause(exception));
+	}
+
+	@Override
+	public boolean isActive() {
+		return experiment.isActive();
+	}
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	@Override
+	public void dispatch(RunAt<? extends Simulator> runnable) {
+		experiment.dispatch((RunAt) runnable);
+	}
+
+	protected final AtomicInteger netloadIdCounter = new AtomicInteger();
+
+	public void uploadNet(final File file, final Future<Object> future) {
+		final String netloadId = "NetLoadSaveLogic" + netloadIdCounter.getAndIncrement();
+
+		log.debug("uploading file {} to {} identified by {}", file, simulatorPath, netloadId);
+
+		final Holder<NeedFileAcceptor> acceptor = new Holder<>();
+		final Tree tree = simulatorPath.getTree();
+
+		acceptor.set(new NeedFileAcceptor() {
+
+			@Override
+			public boolean acceptNeed(NeedFile needFile) {
+				if (!needFile.getDescription().equals(netloadId)) {
+					return false;
+				}
+				log.debug("accepting netload {}", netloadId);
+				needFile.getFuture().pass(file);
+				tree.dispatch(new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
+
+					@Override
+					protected void runAt() {
+						tree.removeNeedFileAcceptor(acceptor.get());
+					}
+				});
+				return true;
+			}
+
+		});
+
+		simulatorPath.getTree().addNeedFileAcceptor(Integer.MIN_VALUE, acceptor.get());
+
+		call(simulatorPath, getFramsClass(simulatorPath).getParamEntry("netload_id", ProcedureParam.class), new Object[] { netloadId }, new FutureHandler<Object>(future) {
+
+			@Override
+			protected void result(Object result) {
+				log.debug("upload of {} done", file);
+				future.pass(result);
+			}
+		});
+
+	}
 }
Index: java/main/src/main/java/com/framsticks/experiment/SimulatorConnector.java
===================================================================
--- java/main/src/main/java/com/framsticks/experiment/SimulatorConnector.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/experiment/SimulatorConnector.java	(revision 102)
@@ -0,0 +1,77 @@
+package com.framsticks.experiment;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.communication.Address;
+import com.framsticks.core.Path;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.remote.RemoteTree;
+import com.framsticks.util.AutoAttacher;
+import com.framsticks.util.Misc;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Strings;
+
+import static com.framsticks.core.TreeOperations.*;
+
+@FramsClassAnnotation
+public class SimulatorConnector implements AutoAttacher {
+	private static final Logger log = LogManager.getLogger(SimulatorConnector.class);
+
+
+	protected Experiment experiment;
+	protected Address address;
+	protected RemoteTree remoteTree;
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	@Override
+	public void attachTo(Object parent) {
+		experiment = Casting.throwCast(Experiment.class, parent);
+
+		Misc.throwIfNull(address);
+		log.debug("connecting to simulator at {}", address);
+		// experiment
+		remoteTree = new RemoteTree();
+		remoteTree.setAddress(address);
+		remoteTree.setDispatcher((Dispatcher) experiment.getDispatcher());
+
+
+		experiment.getSimulatorCandidates().add(remoteTree);
+
+		Dispatching.dispatchLog(remoteTree, log, Level.DEBUG, "first task in remote tree");
+
+		tryGet(remoteTree, "/simulator", new FutureHandler<Path>(experiment) {
+
+			@Override
+			protected void result(Path result) {
+				log.debug("resolved simulator path: {}", result);
+				Misc.checkEquals(experiment.getExpdef(), bindAccess(result).get("expdef", String.class), "expdef mismatch in connected simulator", this);
+
+				Simulator simulator = new Simulator(experiment, remoteTree, result);
+				experiment.addSimulator(simulator);
+				experiment.getSimulatorCandidates().remove(remoteTree);
+			}
+		});
+	}
+
+	@ParamAnnotation
+	public void setAddress(String address) {
+		this.address = new Address(address);
+	}
+
+	@ParamAnnotation
+	public String getAddress() {
+		return Strings.toStringNullProof(address, "");
+	}
+
+	@Override
+	public String toString() {
+		return "simulator connector to: " + Strings.toStringNullProof(address, "<null>");
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/experiment/WorkPackage.java
===================================================================
--- java/main/src/main/java/com/framsticks/experiment/WorkPackage.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/experiment/WorkPackage.java	(revision 102)
@@ -0,0 +1,5 @@
+package com.framsticks.experiment;
+
+public interface WorkPackage {
+
+}
Index: java/main/src/main/java/com/framsticks/experiment/WorkPackageLogic.java
===================================================================
--- java/main/src/main/java/com/framsticks/experiment/WorkPackageLogic.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/experiment/WorkPackageLogic.java	(revision 102)
@@ -0,0 +1,57 @@
+package com.framsticks.experiment;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.communication.File;
+import com.framsticks.params.ListSource;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
+
+@FramsClassAnnotation
+public abstract class WorkPackageLogic<WP extends WorkPackage> extends AbstractExperimentLogic {
+
+	private static final Logger log = LogManager.getLogger(WorkPackageLogic.class);
+
+	@ParamAnnotation
+	public final NetLoadSaveLogic netLoadSaveLogic;
+
+	/**
+	 * @param experiment
+	 */
+	public WorkPackageLogic(Experiment experiment) {
+		super(experiment);
+
+		netLoadSaveLogic = new NetLoadSaveLogic(experiment) {
+
+			@Override
+			public void netload(Simulator simulator, final Future<File> net) {
+				assert experiment.isActive();
+				log.debug("providing netload file for {}", simulator);
+
+				generateNextPackage(new FutureHandler<WP> (net) {
+
+					@Override
+					protected void result(WP result) {
+						log.debug("sending package: {}", result);
+						File file = new File("test-file", ListSource.createFrom("# a test"));
+
+						net.pass(file);
+					}
+				});
+
+			}
+
+			@Override
+			public void netsave(Simulator simulator, File net) {
+				// processFile();
+			}
+		};
+	}
+
+
+	protected abstract void generateNextPackage(Future<WP> future);
+
+}
Index: java/main/src/main/java/com/framsticks/gui/Browser.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 102)
@@ -6,4 +6,6 @@
 import com.framsticks.core.*;
 import com.framsticks.gui.console.Console;
+import com.framsticks.gui.console.DirectConsole;
+import com.framsticks.gui.console.ManagedConsole;
 import com.framsticks.gui.console.TrackConsole;
 import com.framsticks.gui.table.ColumnsConfig;
@@ -56,7 +58,7 @@
 	private static final Logger log = LogManager.getLogger(Browser.class);
 
-	protected final JoinableCollection<Frame> frames = new JoinableCollection<Frame>().setObservableName("frames");
-	protected final JoinableCollection<Tree> trees = new JoinableCollection<Tree>().setObservableName("trees");
-	protected final JoinableCollection<Console> consoles = new JoinableCollection<Console>().setObservableName("consoles");
+	protected final JoinableCollection<Frame> frames = new JoinableCollection<Frame>(JoinableCollection.FinishPolicy.OnAll).setObservableName("frames");
+	protected final JoinableCollection<Tree> trees = new JoinableCollection<Tree>(JoinableCollection.FinishPolicy.Never).setObservableName("trees");
+	protected final JoinableCollection<Console> consoles = new JoinableCollection<Console>(JoinableCollection.FinishPolicy.Never).setObservableName("consoles");
 
 	protected final List<PopupMenuEntryProvider> popupMenuEntryProviders = new LinkedList<>();
@@ -123,7 +125,18 @@
 					}
 				});
-			}
-		});
-		// addNodeActionToTreePopupMenu("", new NodeAction() )
+				menu.add(new AbstractAction("Open managed console") {
+					@Override
+					public void actionPerformed(ActionEvent e) {
+						consoles.add(new ManagedConsole().setTree(remoteTree));
+					}
+				});
+				menu.add(new AbstractAction("Open direct console") {
+					@Override
+					public void actionPerformed(ActionEvent e) {
+						consoles.add(new DirectConsole().setAddress(remoteTree.getAddress()));
+					}
+				});
+			}
+		});
 
 	}
Index: java/main/src/main/java/com/framsticks/gui/Frame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 102)
@@ -95,5 +95,5 @@
 
 	protected final Map<Tree, TreeAtFrame> treeAtFrames = new IdentityHashMap<>();
-	protected JoinableCollection<Tree> trees = new JoinableCollection<>();
+	protected JoinableCollection<Tree> trees = new JoinableCollection<Tree>().setObservableName("frame trees");
 
 	public Frame(Browser browser) {
Index: java/main/src/main/java/com/framsticks/gui/MainFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/MainFrame.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/MainFrame.java	(revision 102)
@@ -51,5 +51,5 @@
 				@Override
 				public void actionPerformed(ActionEvent actionEvent) {
-					browser.autoResolvePath("/simulator/genepools/groups/0", null);
+					// browser.autoResolvePath("/simulator/genepools/groups/0", null);
 					// browser.autoResolvePath("/simulator/populations/groups/0", null;
 					// browser.autoResolvePath("/simulator/genepools/groups/0/genotypes", null);
Index: java/main/src/main/java/com/framsticks/gui/console/DirectConsole.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/DirectConsole.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/console/DirectConsole.java	(revision 102)
@@ -4,8 +4,9 @@
 import java.util.List;
 
+import com.framsticks.communication.Address;
 import com.framsticks.communication.ClientSideRawConnection;
 import com.framsticks.communication.ConnectionListener;
-import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
 import com.framsticks.util.dispatching.ThrowExceptionHandler;
 
@@ -19,7 +20,13 @@
 	}
 
-	@AutoAppendAnnotation
-	public DirectConsole setConnection(ClientSideRawConnection connection) {
-		this.connection = connection;
+
+	@ParamAnnotation
+	public DirectConsole setAddress(String address) {
+		return setAddress(new Address(address));
+	}
+
+	public DirectConsole setAddress(Address address) {
+		this.connection = new ClientSideRawConnection();
+		this.connection.setAddress(address);
 		return this;
 	}
Index: java/main/src/main/java/com/framsticks/gui/console/InteractiveConsole.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/InteractiveConsole.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/console/InteractiveConsole.java	(revision 102)
@@ -54,5 +54,4 @@
 	@Override
 	protected void initializeGui() {
-		// TODO Auto-generated method stub
 		super.initializeGui();
 
Index: java/main/src/main/java/com/framsticks/gui/console/ManagedConsole.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/ManagedConsole.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/console/ManagedConsole.java	(revision 102)
@@ -46,4 +46,5 @@
 		return (ClientSideManagedConnection) connection;
 	}
+
 
 	protected void sendImplementation(String line) {
@@ -159,7 +160,8 @@
 
 	@AutoAppendAnnotation
-	public void setTree(RemoteTree tree) {
+	public ManagedConsole setTree(RemoteTree tree) {
 		this.tree = tree;
 		connection = tree.getConnection();
+		return this;
 	}
 
Index: java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 102)
@@ -6,7 +6,5 @@
 import com.framsticks.params.Param;
 import com.framsticks.params.types.ProcedureParam;
-import com.framsticks.util.dispatching.ExceptionResultHandler;
 import com.framsticks.util.dispatching.FutureHandler;
-import com.framsticks.util.dispatching.ThrowExceptionHandler;
 
 import javax.swing.*;
@@ -60,6 +58,5 @@
 					log.debug("argument {}: {}", arg, value);
 				}
-				//TODO FEH: make it show dialog
-				callProcedure(path, getParam(), arguments.toArray());
+				callProcedure(path, getParam(), arguments.toArray(), getFrame());
 
 			}
@@ -72,10 +69,9 @@
 
 
-	public static void callProcedure(final Path path, final ProcedureParam param, Object[] arguments) {
-		final ExceptionResultHandler handler = ThrowExceptionHandler.getInstance();
+	public static void callProcedure(final Path path, final ProcedureParam param, Object[] arguments, Frame frame) {
 
 		assert path.getTree().isActive();
 
-		path.getTree().call(path, param, arguments, new FutureHandler<Object>(handler) {
+		path.getTree().call(path, param, arguments, new FutureHandler<Object>(frame) {
 
 			@Override
@@ -116,5 +112,4 @@
 	@Override
 	protected void refreshTable() {
-		// TODO Auto-generated method stub
 
 	}
@@ -122,5 +117,4 @@
 	@Override
 	protected void clearTable() {
-		// TODO Auto-generated method stub
 
 	}
Index: java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 102)
@@ -39,4 +39,5 @@
 	private final int div = 10;
 	private JComponent changing = null;
+	public final static float LINE_HEIGHT_FACTOR = 1.2f;
 
 	private Class<? extends Number> valueType;
@@ -46,6 +47,5 @@
 		text = new JTextField();
 
-		//TODO: that factor should be done as a constant
-		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, (int)(LINE_HEIGHT * 1.2)));
+		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, (int)(LINE_HEIGHT * LINE_HEIGHT_FACTOR)));
 
 		// ComponentUI ui = UIManager.getUI(slider);
Index: java/main/src/main/java/com/framsticks/gui/table/ProcedureColumn.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/ProcedureColumn.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/table/ProcedureColumn.java	(revision 102)
@@ -38,5 +38,5 @@
 			return 0;
 		}
-		ProcedureControl.callProcedure(path, getParam(), new Object[] {});
+		ProcedureControl.callProcedure(path, getParam(), new Object[] {}, tableModel.getFrame());
 		return 0;
 	}
Index: java/main/src/main/java/com/framsticks/gui/table/TableModel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/TableModel.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/table/TableModel.java	(revision 102)
@@ -13,4 +13,5 @@
 import org.apache.logging.log4j.LogManager;
 
+import com.framsticks.gui.Frame;
 import com.framsticks.params.Access;
 import com.framsticks.params.ListAccess;
@@ -166,3 +167,7 @@
 	}
 
+	public Frame getFrame() {
+		return listPanel.getFrame();
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/gui/tree/EmptyNode.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/tree/EmptyNode.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/tree/EmptyNode.java	(revision 102)
@@ -42,5 +42,4 @@
 	@Override
 	public void render(TreeCellRenderer renderer) {
-		// TODO Auto-generated method stub
 
 		renderer.setToolTipText("?");
Index: java/main/src/main/java/com/framsticks/gui/tree/TreeCellRenderer.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/tree/TreeCellRenderer.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/gui/tree/TreeCellRenderer.java	(revision 102)
@@ -89,7 +89,5 @@
 
 		}
-
-
-		return ImageProvider.SERVER;
+		return ImageProvider.FOLDER_OPEN;
 	}
 
Index: java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java	(revision 102)
@@ -30,4 +30,5 @@
 
 import static com.framsticks.core.TreeOperations.*;
+import static com.framsticks.params.AccessOperations.*;
 
 import java.net.Socket;
@@ -61,4 +62,5 @@
 		cliObject = new Cli(this);
 		rootTree = new LocalTree();
+		rootTree.setName(server.getName() + " root tree");
 		// rootTree.setDispatcher(new AtOnceDispatcher<Tree>());
 		rootTree.setDispatcher(server.getHosted().getDispatcher());
@@ -114,5 +116,5 @@
 	public static File printToFile(String path, Access access) {
 		ListSink sink = new ListSink();
-		access.save(sink);
+		save(access, sink);
 		return new File(path, new ListSource(sink.getOut()));
 	}
@@ -143,5 +145,4 @@
 				if (request instanceof SetRequest) {
 					SetRequest setRequest = (SetRequest) request;
-					//TODO Primitive Param?
 					tree.set(path, access.getFramsClass().getParamEntry(setRequest.getField(), PrimitiveParam.class), setRequest.getValue(), new FutureHandler<Integer>(responseCallback) {
 						@Override
@@ -198,8 +199,10 @@
 	protected void joinableStart() {
 		Dispatching.use(connection, this);
+		Dispatching.use(rootTree, this);
 	}
 
 	@Override
 	protected void joinableInterrupt() {
+		Dispatching.drop(rootTree, this);
 		Dispatching.drop(connection, this);
 	}
@@ -207,4 +210,5 @@
 	@Override
 	protected void joinableFinish() {
+
 	}
 
@@ -212,4 +216,5 @@
 	protected void joinableJoin() throws InterruptedException {
 		Dispatching.join(connection);
+		Dispatching.join(rootTree);
 	}
 
Index: java/main/src/main/java/com/framsticks/hosting/Server.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/Server.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/hosting/Server.java	(revision 102)
@@ -37,5 +37,5 @@
 	protected ServerSocket acceptSocket;
 	protected Tree hosted;
-	protected final JoinableCollection<ClientAtServer> clients = new JoinableCollection<ClientAtServer>();
+	protected final JoinableCollection<ClientAtServer> clients = new JoinableCollection<ClientAtServer>(JoinableCollection.FinishPolicy.Never);
 
 	public static class Accept {
@@ -68,16 +68,4 @@
 	}
 
-	@Override
-	protected void joinableInterrupt() {
-		Dispatching.drop(acceptThread, this);
-		Dispatching.drop(hosted, this);
-		Dispatching.drop(clients, this);
-		try {
-			acceptSocket.close();
-		} catch (IOException e) {
-			log.debug("exception caught during socket closing: ", e);
-		}
-		finishJoinable();
-	}
 
 	/**
@@ -101,17 +89,4 @@
 	public void childChangedState(Joinable joinable, JoinableState state) {
 		proceedToState(state);
-	}
-
-	@Override
-	protected void joinableStart() {
-		Dispatching.use(acceptThread, this);
-		Dispatching.use(hosted, this);
-		Dispatching.use(clients, this);
-		try {
-			acceptSocket = new ServerSocket();
-		} catch (IOException e) {
-			throw new FramsticksException().msg("failed to create server socket").cause(e);
-		}
-		tryBind(0);
 	}
 
@@ -175,4 +150,34 @@
 	}
 
+
+	@Override
+	protected void joinableStart() {
+		Dispatching.use(acceptThread, this);
+		Dispatching.use(hosted, this);
+		Dispatching.use(clients, this);
+		try {
+			acceptSocket = new ServerSocket();
+			acceptSocket.setReuseAddress(true);
+		} catch (IOException e) {
+			throw new FramsticksException().msg("failed to create server socket").cause(e);
+		}
+		tryBind(0);
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		Dispatching.drop(acceptThread, this);
+		Dispatching.drop(hosted, this);
+		Dispatching.drop(clients, this);
+
+		try {
+			acceptSocket.close();
+		} catch (IOException e) {
+			log.debug("exception caught during socket closing: ", e);
+		}
+
+		finishJoinable();
+	}
+
 	@Override
 	protected void joinableFinish() {
Index: java/main/src/main/java/com/framsticks/model/Model.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Model.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/model/Model.java	(revision 102)
@@ -37,5 +37,5 @@
 	public final List<NeuroConnection> neuroConnections = new ArrayList<NeuroConnection>();
 
-	//TODO: why those methods returns and accepts doubles?
+	/** Those methods accept doubles to keep consistency with Framsticks server.*/
 	@ParamAnnotation
 	public double getNumparts() { return (double)parts.size(); }
Index: java/main/src/main/java/com/framsticks/params/Access.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Access.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/Access.java	(revision 102)
@@ -44,6 +44,4 @@
 	void regRemove(EventParam param, EventListener<?> listener);
 
-	void save(SinkInterface sink);
-
 	/**
 	 * Removes all the properties values.
@@ -71,4 +69,3 @@
 	ParamBuilder buildParam(ParamBuilder builder);
 
-
 }
Index: java/main/src/main/java/com/framsticks/params/AccessOperations.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/AccessOperations.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/AccessOperations.java	(revision 102)
@@ -10,4 +10,5 @@
 
 import static com.framsticks.params.SetStateFlags.*;
+import static com.framsticks.util.lang.Containers.filterInstanceof;
 
 public final class AccessOperations {
@@ -74,5 +75,40 @@
 	}
 
+	public static void save(Access access, Sink sink) {
+		if (access instanceof ObjectAccess) {
+			ObjectAccess objectAccess = (ObjectAccess) access;
+			FramsClass framsClass = access.getFramsClass();
+			assert framsClass != null;
+			sink.print(framsClass.getId()).print(":").breakLine();
+			for (PrimitiveParam<?> p : filterInstanceof(framsClass.getParamEntries(), PrimitiveParam.class)) {
+				Object value = objectAccess.get(p, Object.class);
+				if ((value == null) || value.equals(p.getDef(Object.class))) {
+					continue;
+				}
+				sink.print(p.getId()).print(":");
+				p.save(sink, value);
+				sink.breakLine();
+			}
+			sink.breakLine();
+			return;
+
+		}
+		if (access instanceof ListAccess) {
+			ListAccess listAccess = (ListAccess) access;
+			for (CompositeParam p : filterInstanceof(listAccess.getParams(), CompositeParam.class)) {
+				Object child = listAccess.get(p, Object.class);
+				//this is probably an assertion
+				assert child != null;
+				save(listAccess.getElementAccess().select(child), sink);
+			}
+			return;
+		}
+		throw new FramsticksException().msg("unknown access category").arg("access", access);
+	}
+
 	public static void load(Access access, Source source) {
+		if (!(access instanceof ObjectAccess)) {
+			throw new FramsticksException().msg("access is not an object access").arg("access", access);
+		}
 		Entry entry;
 		while ((entry = readEntry(source)) != null) {
Index: java/main/src/main/java/com/framsticks/params/ListAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 102)
@@ -3,5 +3,4 @@
 
 
-import static com.framsticks.util.lang.Containers.filterInstanceof;
 
 import com.framsticks.params.types.EventParam;
@@ -30,15 +29,4 @@
 
 
-	@Override
-	public void save(SinkInterface sink) {
-		for (CompositeParam p : filterInstanceof(getParams(), CompositeParam.class)) {
-			Object child = get(p, Object.class);
-			//this is probably an assertion
-			assert child != null;
-			elementAccess.select(child);
-			elementAccess.save(sink);
-		}
-	}
-
 	public Access getElementAccess() {
 		return elementAccess;
@@ -57,8 +45,7 @@
 	}
 
-	//TODO it could actually be used also
 	@Override
 	public void tryAutoAppend(Object object) {
-		throw new InvalidOperationException();
+		throw new InvalidOperationException().msg("It could actually be used also, the Access.select could be used to check whether type is correct");
 	}
 
Index: java/main/src/main/java/com/framsticks/params/ListSink.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ListSink.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/ListSink.java	(revision 102)
@@ -7,5 +7,5 @@
  * @author Piotr Sniegowski
  */
-public class ListSink implements SinkInterface {
+public class ListSink implements Sink {
 	protected final List<String> out;
 	protected StringBuilder lineBuilder = new StringBuilder();
@@ -25,5 +25,5 @@
 
 	@Override
-	public SinkInterface print(String str) {
+	public Sink print(String str) {
 		lineBuilder.append(str);
 		return this;
@@ -31,5 +31,5 @@
 
 	@Override
-	public SinkInterface print(Object obj) {
+	public Sink print(Object obj) {
 		lineBuilder.append(obj);
 		return this;
Index: java/main/src/main/java/com/framsticks/params/Param.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Param.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/Param.java	(revision 102)
@@ -35,5 +35,4 @@
 	protected final int flags;
 
-	//TODO
 	/** The variable determining whether the parameter is an extra parameter. */
 	protected final int extra;
Index: java/main/src/main/java/com/framsticks/params/ParamCandidate.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ParamCandidate.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/ParamCandidate.java	(revision 102)
@@ -25,4 +25,5 @@
 import com.framsticks.params.annotations.ParamAnnotation;
 import com.framsticks.params.types.ProcedureParam;
+// import com.framsticks.util.FramsticksException;
 
 public class ParamCandidate {
@@ -477,5 +478,4 @@
 			Type rawType = p.getRawType();
 			Type containedType = null;
-			//TODO make implementation here
 			boolean map = false;
 			StringBuilder b = new StringBuilder();
@@ -490,4 +490,7 @@
 				containedType = p.getActualTypeArguments()[0];
 				b.append("e");
+			} else {
+				return induceParamType(builder, rawType);
+				// throw new FramsticksException().msg("unknown raw type").arg("raw type", rawType);
 			}
 			if (!(containedType instanceof Class)) {
@@ -503,5 +506,4 @@
 			dependantClasses.add(containedClass);
 			b.append(FramsClassBuilder.getName(fca, containedClass));
-			//TODO parameterize this
 			if (map) {
 				b.append(" uid");
@@ -516,5 +518,5 @@
 			Class<?> cl = (Class<?>) type;
 
-			// TODO: future support for enum
+			// this is draft implementation of future support for enum
 			// if (cl.isEnum()) {
 			//	Class<? extends Enum<?>> enumType = (Class<? extends Enum<?>>) cl;
Index: java/main/src/main/java/com/framsticks/params/PrimitiveParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/PrimitiveParam.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/PrimitiveParam.java	(revision 102)
@@ -33,5 +33,5 @@
 	}
 
-	public void save(SinkInterface sink, Object value) {
+	public void save(Sink sink, Object value) {
 		sink.print(value);
 	}
Index: java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 102)
@@ -2,5 +2,4 @@
 
 
-import static com.framsticks.util.lang.Containers.filterInstanceof;
 
 
@@ -103,19 +102,4 @@
 	}
 
-	@Override
-	public void save(SinkInterface sink) {
-		assert framsClass != null;
-		sink.print(framsClass.getId()).print(":").breakLine();
-		for (PrimitiveParam<?> p : filterInstanceof(framsClass.getParamEntries(), PrimitiveParam.class)) {
-			Object value = get(p, Object.class);
-			if ((value == null) || value.equals(p.getDef(Object.class))) {
-				continue;
-			}
-			sink.print(p.getId()).print(":");
-			p.save(sink, value);
-			sink.breakLine();
-		}
-		sink.breakLine();
-	}
 
 	protected abstract <T> void internalSet(ValueParam param, T value);
Index: java/main/src/main/java/com/framsticks/params/SimpleUniqueList.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/SimpleUniqueList.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/SimpleUniqueList.java	(revision 102)
@@ -46,6 +46,11 @@
 	}
 
-	public void fireChildrenChange(T child, ListChange.Action action) {
-		ListChange change = new ListChange(action, UniqueListAccess.getNumberInMap(children, child), child.getUid());
+	public void fireChildrenChange(ListChange original, ListChange.Action action, Object... hints) {
+		listeners.actionForAll(new ListChange(action, original.getPosition(), original.getIdentifier(), hints));
+
+	}
+
+	public void fireChildrenChange(T child, ListChange.Action action, Object... hints) {
+		ListChange change = new ListChange(action, UniqueListAccess.getNumberInMap(children, child), child.getUid(), hints);
 		listeners.actionForAll(change);
 	}
Index: java/main/src/main/java/com/framsticks/params/Sink.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Sink.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/params/Sink.java	(revision 102)
@@ -0,0 +1,11 @@
+package com.framsticks.params;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public interface Sink {
+	Sink print(String str);
+	Sink print(Object obj);
+	void breakLine();
+	void close();
+}
Index: java/main/src/main/java/com/framsticks/params/SinkInterface.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/SinkInterface.java	(revision 101)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package com.framsticks.params;
-
-/**
- * @author Piotr Sniegowski
- */
-public interface SinkInterface {
-	SinkInterface print(String str);
-	SinkInterface print(Object obj);
-	void breakLine();
-	void close();
-}
Index: java/main/src/main/java/com/framsticks/params/types/BooleanParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/BooleanParam.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/types/BooleanParam.java	(revision 102)
@@ -7,5 +7,5 @@
 import com.framsticks.params.PrimitiveParam;
 import com.framsticks.params.ReassignResult;
-import com.framsticks.params.SinkInterface;
+import com.framsticks.params.Sink;
 import com.framsticks.util.lang.Numbers;
 
@@ -58,5 +58,5 @@
 
 	@Override
-	public void save(SinkInterface sink, Object value) {
+	public void save(Sink sink, Object value) {
 		assert value instanceof Boolean;
 		sink.print(((Boolean)value) ? "1" : "0");
Index: java/main/src/main/java/com/framsticks/params/types/StringParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/StringParam.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/params/types/StringParam.java	(revision 102)
@@ -5,5 +5,5 @@
 import com.framsticks.params.PrimitiveParam;
 import com.framsticks.params.ReassignResult;
-import com.framsticks.params.SinkInterface;
+import com.framsticks.params.Sink;
 
 import javax.annotation.concurrent.Immutable;
@@ -49,5 +49,5 @@
 
 	@Override
-	public void save(SinkInterface sink, Object value) {
+	public void save(Sink sink, Object value) {
 		assert value instanceof String;
 		String s = (String)value;
Index: java/main/src/main/java/com/framsticks/parsers/F0Writer.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/F0Writer.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/parsers/F0Writer.java	(revision 102)
@@ -15,9 +15,9 @@
 
 	protected final Schema schema;
-	protected final SinkInterface sink;
+	protected final Sink sink;
 	protected final Model model;
 	protected boolean omitDefaults = true;
 
-	public F0Writer(Schema schema, Model model, SinkInterface sink) {
+	public F0Writer(Schema schema, Model model, Sink sink) {
 		this.schema = schema;
 		this.model = model;
@@ -32,5 +32,4 @@
 	protected void write(Access access) {
 		if (access instanceof ListAccess) {
-			// TODO
 			for (ValueParam p : Containers.filterInstanceof(access.getParams(), ValueParam.class)) {
 				write(schema.getRegistry().prepareAccess((CompositeParam) p).select(access.get(p, Object.class)));
Index: java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java	(revision 102)
@@ -23,5 +23,4 @@
 	}
 
-	/** TODO does it support multilines? */
 	/**
 	 * Specifies the condition to break execution.
Index: java/main/src/main/java/com/framsticks/parsers/Savers.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/Savers.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/parsers/Savers.java	(revision 102)
@@ -1,6 +1,10 @@
 package com.framsticks.parsers;
 
-import com.framsticks.params.*;
-import com.framsticks.params.SinkInterface;
+import com.framsticks.params.Access;
+import com.framsticks.params.FramsClass;
+import com.framsticks.params.Param;
+import com.framsticks.params.ReflectionAccess;
+import com.framsticks.params.Sink;
+import static com.framsticks.params.AccessOperations.*;
 
 /**
@@ -8,13 +12,13 @@
  */
 public class Savers {
-	public static <S extends SinkInterface> S saveFramsClass(S sink, FramsClass framsClass) {
+	public static <S extends Sink> S saveFramsClass(S sink, FramsClass framsClass) {
 
 		Access framsClassAccess = new ReflectionAccess(FramsClass.class);
 		Access paramAccess = new ReflectionAccess(Param.class);
 		framsClassAccess.select(framsClass);
-		framsClassAccess.save(sink);
+
+		save(framsClassAccess, sink);
 		for (Param p : framsClass.getParamEntries()) {
-			paramAccess.select(p);
-			paramAccess.save(sink);
+			save(paramAccess.select(p), sink);
 		}
 		return sink;
Index: java/main/src/main/java/com/framsticks/parsers/XmlLoader.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/XmlLoader.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/parsers/XmlLoader.java	(revision 102)
@@ -23,4 +23,5 @@
 import com.framsticks.params.PrimitiveParam;
 import com.framsticks.params.Registry;
+import com.framsticks.util.AutoAttacher;
 import com.framsticks.util.AutoBuilder;
 import com.framsticks.util.FramsticksException;
@@ -137,5 +138,9 @@
 
 			for (Object child : childrenObjects) {
-				access.tryAutoAppend(child);
+				if (child instanceof AutoAttacher) {
+					((AutoAttacher) child).attachTo(access.getSelected());
+				} else {
+					access.tryAutoAppend(child);
+				}
 			}
 		}
Index: java/main/src/main/java/com/framsticks/remote/RemoteTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/RemoteTree.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/remote/RemoteTree.java	(revision 102)
@@ -56,9 +56,13 @@
 	}
 
+	public void setAddress(Address address) {
+		this.connection = Connection.to(new ClientSideManagedConnection(), address);
+		this.connection.setExceptionHandler(this);
+		this.connection.setNeedFileAcceptor(this);
+	}
+
 	@ParamAnnotation
 	public void setAddress(String address) {
-		this.connection = Connection.to(new ClientSideManagedConnection(), new Address(address));
-		this.connection.setExceptionHandler(this);
-		this.connection.setNeedFileAcceptor(this);
+		setAddress(new Address(address));
 	}
 
@@ -72,8 +76,8 @@
 	}
 
+
 	@Override
 	public String toString() {
-		assert Dispatching.isThreadSafe();
-		return "remote tree " + getName() + "(" + getAddress() + ")";
+		return super.toString() + "[" + getAddress() + "]";
 	}
 
@@ -102,5 +106,4 @@
 	//	assert param != null;
 	//	// assert path.isResolved();
-	//	//TODO only do that if needed
 	//	connection.send(new GetRequest().field(param.getId()).path(path.getTextual()), this, new ClientSideResponseFuture(pathRemoveHandler(path, future)) {
 	//		@Override
@@ -116,4 +119,10 @@
 
 
+	/** Fetch information.
+ 	 *
+	 * This method does not check whether the info is already in the cache, it will always issue a request or join
+	 * with other already issued but returned info request. Too issue request only when needed, use TreeOperations.findInfo()
+	 *
+	 * */
 	@Override
 	public void info(final Path path, final Future<FramsClass> future) {
@@ -153,5 +162,4 @@
 		});
 
-		//TODO: if the info is in the cache, then don't communicate
 		connection.send(new InfoRequest().path(path.getTextual()), AtOnceDispatcher.getInstance(), new ClientSideResponseFuture(compositeFuture) {
 			@Override
@@ -203,5 +211,5 @@
 
 		log.trace("storing value {} for {}", param, path);
-		//TODO break in passing exception handler is here
+
 		connection.send(new SetRequest().value(value.toString()).field(param.getId()).path(path.getTextual()), this, new ClientSideResponseFuture(future) {
 			@Override
@@ -224,5 +232,8 @@
 					@Override
 					protected void processOk(Response response) {
-						FramsClass framsClass = processFetchedInfo(RemoteTree.this, response.getFiles().get(0));
+						assert bufferedDispatcher.getTargetDispatcher().isActive();
+						FramsClass framsClass = Loaders.loadFramsClass(response.getFiles().get(0).getContent());
+						putInfoIntoCache(framsClass);
+
 						assignRootParam(Param.build().name("Tree").id(RemoteTree.this.getName()).type("o " + framsClass.getId()).finish(CompositeParam.class));
 						bufferedDispatcher.setBuffer(false);
Index: java/main/src/main/java/com/framsticks/running/ExternalProcess.java
===================================================================
--- java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 102)
@@ -22,5 +22,4 @@
 import com.framsticks.params.annotations.ParamAnnotation;
 import com.framsticks.util.FramsticksException;
-import com.framsticks.util.Misc;
 import com.framsticks.util.dispatching.AbstractJoinable;
 import com.framsticks.util.dispatching.Dispatching;
@@ -110,5 +109,5 @@
 				throw new FramsticksException().msg("failed to wait for process").cause(e);
 			}
-			log.debug("process ended {}", this);
+			log.info("process ended {}", this);
 			// process = null;
 		} catch (FramsticksException e) {
@@ -131,5 +130,5 @@
 	@Override
 	protected void joinableStart() {
-		log.debug("running process with arguments: {}", arguments);
+		log.debug("running process {}", this);
 		builder.command(arguments);
 		try {
@@ -160,5 +159,5 @@
 	@Override
 	public String toString() {
-		return getName() + "[" + Misc.returnNotNull(getCommand(), "?") + "]";
+		return getName() + arguments;
 	}
 
Index: java/main/src/main/java/com/framsticks/running/FramsServer.java
===================================================================
--- java/main/src/main/java/com/framsticks/running/FramsServer.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/running/FramsServer.java	(revision 102)
@@ -1,6 +1,10 @@
 package com.framsticks.running;
 
+
+
+import com.framsticks.params.ParamFlags;
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.util.lang.Strings;
 
 @FramsClassAnnotation
@@ -9,4 +13,5 @@
 	protected Integer port;
 	protected String path;
+	protected String expdef;
 
 	/**
@@ -23,5 +28,5 @@
 	 * @return the port
 	 */
-	@ParamAnnotation
+	@ParamAnnotation(flags = ParamFlags.USERREADONLY)
 	public Integer getPort() {
 		return port;
@@ -39,5 +44,5 @@
 	 * @return the path
 	 */
-	@ParamAnnotation
+	@ParamAnnotation(flags = ParamFlags.USERREADONLY)
 	public String getPath() {
 		return path;
@@ -54,4 +59,20 @@
 	}
 
+	/**
+	 * @return the expdef
+	 */
+	@ParamAnnotation(flags = ParamFlags.USERREADONLY)
+	public String getExpdef() {
+		return expdef;
+	}
+
+	/**
+	 * @param expdef the expdef to set
+	 */
+	@ParamAnnotation
+	public void setExpdef(String expdef) {
+		this.expdef = expdef;
+	}
+
 	@Override
 	protected void joinableStart() {
@@ -60,4 +81,8 @@
 			arguments.add("-p" + port);
 		}
+		if (Strings.notEmpty(expdef)) {
+			arguments.add("Simulator.expdef=\"" + expdef + "\";");
+		}
+		// log.debug("running {} with arguments {}", getCommand(), arguments);
 		super.joinableStart();
 	}
Index: java/main/src/main/java/com/framsticks/test/PrimeExperiment.java
===================================================================
--- java/main/src/main/java/com/framsticks/test/PrimeExperiment.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/test/PrimeExperiment.java	(revision 102)
@@ -1,9 +1,52 @@
 package com.framsticks.test;
 
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
 import com.framsticks.experiment.Experiment;
+import com.framsticks.experiment.WorkPackageLogic;
 import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.test.prime.PrimePackage;
+import com.framsticks.util.dispatching.Future;
 
 @FramsClassAnnotation
 public class PrimeExperiment extends Experiment {
+	private static final Logger log = LogManager.getLogger(PrimeExperiment.class);
+
+	@ParamAnnotation
+	public final WorkPackageLogic<PrimePackage> workPackageLogic;
+
+	protected int maxNumber = 3000;
+	protected int step = 100;
+	protected int numberCounter = 1;
+
+	/**
+	 *
+	 */
+	public PrimeExperiment() {
+		setExpdef("prime");
+
+		workPackageLogic = new WorkPackageLogic<PrimePackage>(this) {
+
+			@Override
+			protected void generateNextPackage(Future<PrimePackage> future) {
+				assert isActive();
+				PrimePackage wp = new PrimePackage();
+
+				log.debug("generated package: {}", wp);
+				wp.params.from_number = numberCounter;
+				numberCounter += step;
+				wp.params.to_number = numberCounter - 1;
+				wp.state.current_number = wp.params.from_number;
+				wp.state.getResultList().clear();
+
+				future.pass(wp);
+			}
+		};
+	}
+
+	protected void processFile() {
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/test/prime/ExpParams.java
===================================================================
--- java/main/src/main/java/com/framsticks/test/prime/ExpParams.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/test/prime/ExpParams.java	(revision 102)
@@ -0,0 +1,19 @@
+package com.framsticks.test.prime;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+
+@FramsClassAnnotation
+public class ExpParams {
+
+	@ParamAnnotation
+	public int from_number;
+
+	@ParamAnnotation
+	public int to_number;
+
+	@Override
+	public String toString() {
+		return "[" + from_number + ":" + to_number + "]";
+	}
+}
Index: java/main/src/main/java/com/framsticks/test/prime/ExpState.java
===================================================================
--- java/main/src/main/java/com/framsticks/test/prime/ExpState.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/test/prime/ExpState.java	(revision 102)
@@ -0,0 +1,43 @@
+package com.framsticks.test.prime;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+
+@FramsClassAnnotation
+public class ExpState {
+
+	@ParamAnnotation
+	public int current_number;
+
+	protected final List<Integer> resultList = new ArrayList<>();
+
+	@ParamAnnotation
+	public String getResult() {
+		return StringUtils.join(resultList, ",");
+	}
+
+	@ParamAnnotation
+	public void setResult(String result) {
+		resultList.clear();
+		for (String s : StringUtils.split(result, ",")) {
+			resultList.add(Integer.valueOf(s));
+		}
+	}
+
+	/**
+	 * @return the resultList
+	 */
+	public List<Integer> getResultList() {
+		return resultList;
+	}
+
+	@Override
+	public String toString() {
+		return "(" + current_number + "):" + resultList;
+	}
+}
Index: java/main/src/main/java/com/framsticks/test/prime/PrimePackage.java
===================================================================
--- java/main/src/main/java/com/framsticks/test/prime/PrimePackage.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/test/prime/PrimePackage.java	(revision 102)
@@ -0,0 +1,18 @@
+package com.framsticks.test.prime;
+
+import com.framsticks.experiment.WorkPackage;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+
+@FramsClassAnnotation
+public class PrimePackage implements WorkPackage {
+
+	public final ExpParams params = new ExpParams();
+
+	public final ExpState state = new ExpState();
+
+	@Override
+	public String toString() {
+		return params + " -> " + state;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/AutoAttacher.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/AutoAttacher.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/util/AutoAttacher.java	(revision 102)
@@ -0,0 +1,7 @@
+package com.framsticks.util;
+
+public interface AutoAttacher {
+
+	public void attachTo(Object parent);
+
+}
Index: java/main/src/main/java/com/framsticks/util/Misc.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Misc.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/util/Misc.java	(revision 102)
@@ -54,3 +54,10 @@
 		return value;
 	}
+
+	public static void checkEquals(Object expected, Object found, String message, Object context) {
+		if (equals(expected, found)) {
+			return;
+		}
+		throw new FramsticksException().msg(message).arg("expected", expected).arg("found", found).arg("in", context);
+	}
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java	(revision 102)
@@ -18,4 +18,5 @@
 
 	private static final Logger log = LogManager.getLogger(AbstractJoinable.class);
+	private static final Logger reportLog = LogManager.getLogger(AbstractJoinable.class.getName() + ".Report");
 
 	protected final Set<JoinableParent> owners = new HashSet<JoinableParent>();
@@ -35,5 +36,10 @@
 	}
 
+
+
 	public static void report() {
+		if (!reportLog.isDebugEnabled()) {
+			return;
+		}
 		StringBuilder b = new StringBuilder();
 		synchronized (joinablesRegistry) {
@@ -42,5 +48,5 @@
 			}
 		}
-		log.debug("state: {}", b);
+		reportLog.debug("state: {}", b);
 	}
 
@@ -53,6 +59,6 @@
 		}
 		this.state = state;
-
-		log.debug("{} is notifying {} parents", this, joinableListeners.size());
+		log.debug("{} changed state to {}", this, state);
+
 
 		List<JoinableParent> parents = new LinkedList<>();
@@ -61,4 +67,5 @@
 		for (JoinableParent p : parents) {
 			if (p != null) {
+				log.debug("{} is notifying parent {} about change to {}", this, p, state);
 				Dispatching.childChangedState(p, this, state);
 			}
@@ -110,7 +117,8 @@
 		}
 		joinableJoin();
-		synchronized (this) {
-			this.state = JoinableState.JOINED;
-		}
+		changeState(JoinableState.JOINED);
+		// synchronized (this) {
+		// 	this.state = JoinableState.JOINED;
+		// }
 	}
 
@@ -158,11 +166,12 @@
 		synchronized (this) {
 			if (!owners.contains(owner)) {
-				return false;
-				// throw new FramsticksException().msg("object is not owning that joinable").arg("joinable", this).arg("object", owner);
+				// log.error("owner {} is not owning that joinable {}", owner, this);
+				// return false;
+				throw new FramsticksException().msg("object is not owning that joinable").arg("joinable", this).arg("object", owner);
 			}
 			// assert owners.containsKey(owner);
-			log.debug("{} is droping {}", owner, this);
 			owners.remove(owner);
 			stop = owners.isEmpty();
+			log.debug("{} is droping {} (users remaining: {})", owner, this, owners);
 		}
 		if (stop) {
@@ -195,5 +204,5 @@
 	@Override
 	public String toString() {
-		return getName();
+		return getClass().getSimpleName() + "(" + getName() + ")";
 	}
 
@@ -203,4 +212,3 @@
 	}
 
-
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/BufferedDispatcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/BufferedDispatcher.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/util/dispatching/BufferedDispatcher.java	(revision 102)
@@ -2,5 +2,13 @@
 
 
-public class BufferedDispatcher<C> {
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.lang.Strings;
+// import static com.framsticks.util.dispatching.AbstractJoinable.wrap;
+
+public class BufferedDispatcher<C> extends AbstractJoinable implements Dispatcher<C>, JoinableParent {
+	private static final Logger log = LogManager.getLogger(BufferedDispatcher.class);
 
 	protected final RunnableQueue<C> queue = new RunnableQueue<>();
@@ -8,5 +16,13 @@
 	protected Dispatcher<C> targetDispatcher;
 
-	protected boolean buffer = false;
+	protected boolean buffer = true;
+	protected Dispatcher<C> parent;
+
+	/**
+	 * @param parent
+	 */
+	public BufferedDispatcher(Dispatcher<C> parent) {
+		this.parent = parent;
+	}
 
 	/**
@@ -21,9 +37,17 @@
 	 */
 	public synchronized void setTargetDispatcher(Dispatcher<C> targetDispatcher) {
+		if (this.targetDispatcher != null) {
+			throw new FramsticksException().msg("dispatcher is already set").arg("dispatcher", this.targetDispatcher).arg("in", this);
+		}
+		if (targetDispatcher == null) {
+			throw new FramsticksException().msg("trying to set empty target dispatcher").arg("in", this);
+		}
+		log.debug("setting {} to {}", this, targetDispatcher);
 		this.targetDispatcher = targetDispatcher;
+		flushQueue();
 	}
 
 	public synchronized boolean isActive() {
-		if (targetDispatcher == null) {
+		if (targetDispatcher == null || buffer) {
 			return false;
 			// throw new FramsticksException().msg("no dispatcher is set for tree yet").arg("tree", this);
@@ -40,4 +64,14 @@
 	}
 
+	protected void flushQueue() {
+		if (this.buffer || targetDispatcher == null) {
+			return;
+		}
+		log.debug("flushing {} tasks in {}", queue.size(), this);
+		while (!queue.isEmpty()) {
+			targetDispatcher.dispatch(queue.pollFirst());
+		}
+	}
+
 	public synchronized void setBuffer(final boolean buffer) {
 		if (this.buffer == buffer) {
@@ -49,10 +83,49 @@
 		}
 		this.buffer = false;
-		while (!queue.isEmpty()) {
-			targetDispatcher.dispatch(queue.pollFirst());
+		flushQueue();
+	}
+
+	@Override
+	public String toString() {
+		return parent + " -> " + Strings.toStringNullProof(targetDispatcher, "<null>");
+	}
+
+	public void createThreadIfNeeded() {
+		if (targetDispatcher != null) {
+			return;
 		}
+		this.setTargetDispatcher(new Thread<C>().setName(parent.getName()));
+	}
+
+	@Override
+	public String getName() {
+		return parent + " buffered dispatcher";
+	}
+
+	@Override
+	protected void joinableStart() {
+		Dispatching.use(targetDispatcher, this);
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		Dispatching.drop(targetDispatcher, this);
+
+		finishJoinable();
+	}
+
+	@Override
+	protected void joinableFinish() {
 
 	}
 
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.join(targetDispatcher);
+	}
 
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		proceedToState(state);
+	}
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/DispatcherSetable.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/DispatcherSetable.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/util/dispatching/DispatcherSetable.java	(revision 102)
@@ -0,0 +1,7 @@
+package com.framsticks.util.dispatching;
+
+public interface DispatcherSetable<C> {
+	public void setDispatcher(Dispatcher<C> dispatcher);
+	public Dispatcher<C> getDispatcher();
+
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 102)
@@ -3,8 +3,10 @@
 import java.util.Timer;
 
+import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.Misc;
 
 /**
@@ -32,4 +34,8 @@
 	}
 
+	public static <C> void dispatch(Dispatcher<C> dispatcher, RunAt<? extends C> runnable) {
+		dispatcher.dispatch(runnable);
+	}
+
 	// public static boolean assertInvokeLater(Dispatcher dispatcher, RunAt runnable) {
 	//	dispatcher.invokeLater(runnable);
@@ -66,4 +72,5 @@
 
 	public static void use(final Joinable joinable, final JoinableParent owner) {
+		Misc.throwIfNull(joinable);
 		log.debug("using {} by {}", joinable, owner);
 		if (joinable.use(owner)) {
@@ -75,4 +82,5 @@
 
 	public static void drop(final Joinable joinable, final JoinableParent owner) {
+		Misc.throwIfNull(joinable);
 		log.debug("droping {} by {}", joinable, owner);
 		if (joinable.drop(owner)) {
@@ -84,4 +92,5 @@
 
 	public static void join(Joinable joinable) throws InterruptedException {
+		Misc.throwIfNull(joinable);
 		log.debug("joining {}", joinable);
 		try {
@@ -95,5 +104,5 @@
 
 	public static void childChangedState(final JoinableParent parent, final Joinable joinable, final JoinableState state) {
-		if (state.ordinal() <= JoinableState.RUNNING.ordinal()) {
+		if (state.ordinal() < JoinableState.RUNNING.ordinal()) {
 			return;
 		}
@@ -113,4 +122,5 @@
 			}
 		} catch (InterruptedException e) {
+			log.debug("failed to wait on {} because of: {}", object, e.getMessage());
 		}
 	}
@@ -123,4 +133,5 @@
 				return;
 			} catch (InterruptedException e) {
+				log.debug("failed to join {} because of: {}", joinable, e.getMessage());
 				// throw new FramsticksException().msg("failed to join").arg("dispatcher", dispatcher).cause(e);
 			}
@@ -192,38 +203,38 @@
 
 	// public static class DispatcherWaiter<C, T extends Dispatcher<C> & Joinable> implements Dispatcher<C> {
-	// 	// protected boolean done = false;
-	// 	protected final T dispatcher;
-	// 	protected RunAt<? extends C> runnable;
-
-	// 	/**
-	// 	 * @param joinable
-	// 	 */
-	// 	public DispatcherWaiter(T dispatcher) {
-	// 		this.dispatcher = dispatcher;
-	// 	}
-
-	// 	public synchronized void waitFor() {
-	// 		while ((runnable == null) && (dispatcher.getState().ordinal() <= JoinableState.RUNNING.ordinal())) {
-	// 			try {
-	// 				this.wait();
-	// 			} catch (InterruptedException e) {
-	// 			}
-	// 		}
-	// 		if (runnable != null) {
-	// 			runnable.run();
-	// 		}
-
-	// 	}
-
-	// 	@Override
-	// 	public boolean isActive() {
-	// 		return dispatcher.isActive();
-	// 	}
-
-	// 	@Override
-	// 	public synchronized void dispatch(RunAt<? extends C> runnable) {
-	// 		this.runnable = runnable;
-	// 		this.notifyAll();
-	// 	}
+	//	// protected boolean done = false;
+	//	protected final T dispatcher;
+	//	protected RunAt<? extends C> runnable;
+
+	//	/**
+	//	 * @param joinable
+	//	 */
+	//	public DispatcherWaiter(T dispatcher) {
+	//		this.dispatcher = dispatcher;
+	//	}
+
+	//	public synchronized void waitFor() {
+	//		while ((runnable == null) && (dispatcher.getState().ordinal() <= JoinableState.RUNNING.ordinal())) {
+	//			try {
+	//				this.wait();
+	//			} catch (InterruptedException e) {
+	//			}
+	//		}
+	//		if (runnable != null) {
+	//			runnable.run();
+	//		}
+
+	//	}
+
+	//	@Override
+	//	public boolean isActive() {
+	//		return dispatcher.isActive();
+	//	}
+
+	//	@Override
+	//	public synchronized void dispatch(RunAt<? extends C> runnable) {
+	//		this.runnable = runnable;
+	//		this.notifyAll();
+	//	}
 
 	// }
@@ -284,3 +295,14 @@
 	}
 
+	public static <C> void dispatchLog(final Dispatcher<C> dispatcher, final Logger logger, final Level level, final Object text) {
+		dispatcher.dispatch(new RunAt<C>(ThrowExceptionHandler.getInstance()) {
+
+			@Override
+			protected void runAt() {
+				logger.log(level, "message dispatched into {}: {}", dispatcher, text);
+			}
+		});
+
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java	(revision 102)
@@ -21,14 +21,24 @@
 	protected final Set<T> joinables = new HashSet<T>();
 
-	protected boolean finishIfOne;
+	public static enum FinishPolicy {
+		Never,
+		OnFirst,
+		OnAll
+	};
+
+	protected final FinishPolicy finishPolicy;
 
 	protected String observableName;
 
 	public JoinableCollection() {
-		this(false);
-	}
-
-	public JoinableCollection(boolean finishIfOne) {
-		this.finishIfOne = finishIfOne;
+		this(FinishPolicy.OnAll);
+	}
+
+
+	/**
+	 * @param finishPolicy
+	 */
+	public JoinableCollection(FinishPolicy finishPolicy) {
+		this.finishPolicy = finishPolicy;
 	}
 
@@ -95,11 +105,12 @@
 
 	protected JoinableState getNextState() {
-		if (joinables.isEmpty()) {
+		if ((finishPolicy == FinishPolicy.Never && state == JoinableState.RUNNING) || joinables.isEmpty()) {
 			return state;
 		}
-		JoinableState result = finishIfOne ? JoinableState.INITILIAZED : JoinableState.JOINED;
+		boolean oneIsEnough = (finishPolicy == FinishPolicy.OnFirst);
+		JoinableState result = oneIsEnough ? JoinableState.INITILIAZED : JoinableState.JOINED;
 		for (Joinable j : joinables) {
 			JoinableState s = j.getState();
-			if (finishIfOne) {
+			if (oneIsEnough) {
 				if (s.ordinal() > result.ordinal()) {
 					result = s;
Index: java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java	(revision 102)
@@ -5,4 +5,5 @@
 import com.framsticks.util.dispatching.Dispatching;
 import java.lang.Thread;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 public class Monitor implements JoinableParent {
@@ -12,4 +13,6 @@
 	protected final Joinable joinable;
 	protected final Thread shutdownHook;
+	protected final AtomicBoolean dropped = new AtomicBoolean(false);
+	protected final AtomicBoolean joining = new AtomicBoolean(false);
 
 	/**
@@ -22,6 +25,8 @@
 			@Override
 			public void run() {
-				log.debug("running shutdown hook");
+				log.debug("droping and joining");
 				Monitor.this.drop().join();
+				log.debug("droped and joined");
+				AbstractJoinable.report();
 			}
 		});
@@ -54,4 +59,7 @@
 
 	public Monitor drop() {
+		if (!dropped.compareAndSet(false, true)) {
+			return this;
+		}
 		log.debug("{} is droping", this);
 		Dispatching.drop(joinable, this);
@@ -60,4 +68,9 @@
 
 	public Monitor join() {
+		if (!joining.compareAndSet(false, true)) {
+			log.debug("not joining");
+			return this;
+		}
+
 		log.debug("{} is joining", this);
 		Dispatching.joinAbsolutely(joinable);
@@ -69,5 +82,4 @@
 			/** In case IllegalStateException is caught, it means that JVM is in finalization stage */
 		}
-
 		return this;
 	}
Index: java/main/src/main/java/com/framsticks/util/dispatching/RunnableQueue.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/RunnableQueue.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/util/dispatching/RunnableQueue.java	(revision 102)
@@ -19,3 +19,7 @@
 	}
 
+	public int size() {
+		return queue.size();
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/StackedJoinable.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/StackedJoinable.java	(revision 102)
+++ java/main/src/main/java/com/framsticks/util/dispatching/StackedJoinable.java	(revision 102)
@@ -0,0 +1,137 @@
+package com.framsticks.util.dispatching;
+
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.TimerTask;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.params.annotations.AutoAppendAnnotation;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+
+@FramsClassAnnotation
+public class StackedJoinable extends AbstractJoinable implements JoinableParent {
+	private static final Logger log = LogManager.getLogger(StackedJoinable.class);
+
+
+	protected final LinkedList<Joinable> joinables = new LinkedList<Joinable>();
+	protected ListIterator<Joinable> iterator;
+	protected Joinable currentJoinable;
+
+	protected double interval = 1;
+
+	/**
+	 *
+	 */
+	public StackedJoinable() {
+		super();
+	}
+
+	@AutoAppendAnnotation
+	public void addJoinable(Joinable joinable) {
+		joinables.add(joinable);
+	}
+
+	@Override
+	public String getName() {
+		return "stacked";
+	}
+
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		// log.error("{} notified {} about changing state to {}", joinable, this, state);
+		if (state.equals(JoinableState.RUNNING)) {
+			if (joinable == currentJoinable) {
+				Dispatching.getTimer().schedule(new TimerTask() {
+					@Override
+					public void run() {
+						startNext();
+					}
+				}, (int)(interval * 1000));
+			}
+			return;
+		}
+		if (state.equals(JoinableState.FINISHING)) {
+			if (joinable == currentJoinable) {
+				Dispatching.getTimer().schedule(new TimerTask() {
+					@Override
+					public void run() {
+						stopNext();
+					}
+				}, (int)(interval * 1000));
+			}
+			return;
+		}
+
+	}
+
+	protected void startNext() {
+		if (!iterator.hasNext()) {
+			currentJoinable = null;
+			log.debug("started all");
+			return;
+		}
+		currentJoinable = iterator.next();
+		log.debug("starting {}", currentJoinable);
+		Dispatching.use(currentJoinable, this);
+	}
+
+	protected void stopNext() {
+		if (!iterator.hasPrevious()) {
+			finishJoinable();
+			return;
+		}
+		currentJoinable = iterator.previous();
+		log.debug("stoping {}", currentJoinable);
+		Dispatching.drop(currentJoinable, this);
+	}
+
+	@Override
+	protected void joinableStart() {
+		iterator = joinables.listIterator();
+		startNext();
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		log.debug("interupting");
+		stopNext();
+	}
+
+	@Override
+	protected void joinableFinish() {
+		// here process ends and StackedJoinable transists to the joinable state
+
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+
+	}
+
+	/**
+	 * @return the interval
+	 */
+	@ParamAnnotation
+	public double getInterval() {
+		return interval;
+	}
+
+	/**
+	 * @param interval the interval to set
+	 */
+	@ParamAnnotation
+	public void setInterval(double interval) {
+		this.interval = interval;
+	}
+
+	public Joinable get(int number) {
+		return joinables.get(number);
+	}
+
+	public int size() {
+		return joinables.size();
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Thread.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 101)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 102)
@@ -106,6 +106,7 @@
 
 	@ParamAnnotation
-	public void setName(String name) {
+	public Thread<C> setName(String name) {
 		thread.setName(name);
+		return this;
 	}
 
@@ -119,8 +120,8 @@
 	}
 
-	@Override
-	public String toString() {
-		return getName();
-	}
+	// @Override
+	// public String toString() {
+	// 	return getName();
+	// }
 
 	@Override
Index: java/main/src/main/resources/common-columns.xml
===================================================================
--- java/main/src/main/resources/common-columns.xml	(revision 101)
+++ java/main/src/main/resources/common-columns.xml	(revision 102)
@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <AutoInjector>
+	<import class="com.framsticks.gui.table.ColumnsConfig" />
 	<ColumnsConfig className="Genotype" columnsNames="uid name mutate" />
 	<ColumnsConfig className="Part" columnsNames="x y z" />
+	<ColumnsConfig className="Simulator" columnsNames="name init stop start abort" />
 </AutoInjector>
Index: java/main/src/main/resources/log4j2.xml
===================================================================
--- java/main/src/main/resources/log4j2.xml	(revision 101)
+++ java/main/src/main/resources/log4j2.xml	(revision 102)
@@ -5,7 +5,7 @@
 			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
 		</Console>
-		<File name="File" fileName="framsticks.log">
-			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
-		</File>
+		<!-- <File name="File" fileName="framsticks.log"> -->
+		<!-- 	<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> -->
+		<!-- </File> -->
 	</appenders>
 	<loggers>
@@ -15,7 +15,15 @@
 		<!-- <logger name="com.framsticks.running.ExternalProcess" level="trace" /> -->
 		<!-- <logger name="com.framsticks.util.dispatching.AbstractJoinable" level="debug" /> -->
+		<!-- <logger name="com.framsticks.util.dispatching.AbstractJoinable.Report" level="info" /> -->
+		<!-- <logger name="com.framsticks.util.dispatching.Monitor" level="debug" /> -->
+		<logger name="com.framsticks.util.dispatching.BufferedDispatcher" level="debug" />
+		<!-- <logger name="com.framsticks.util.dispatching.Dispatching" level="debug" /> -->
+		<logger name="com.framsticks.running" level="debug" />
+		<!-- <logger name="com.framsticks.communication" level="debug" /> -->
+		<logger name="com.framsticks.experiment" level="debug" />
+		<logger name="com.framsticks.experiment.Simulator" level="debug" />
 		<root level="info">
 			<appender-ref ref="Console"/>
-			<appender-ref ref="File"/>
+			<!-- <appender-ref ref="File"/> -->
 		</root>
 	</loggers>
Index: java/main/src/main/resources/prime-all.xml
===================================================================
--- java/main/src/main/resources/prime-all.xml	(revision 102)
+++ java/main/src/main/resources/prime-all.xml	(revision 102)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Framsticks>
+	<import class="com.framsticks.util.dispatching.StackedJoinable" />
+	<StackedJoinable interval="1">
+		<include resource="/prime-servers.xml" />
+		<include resource="/prime.xml" />
+		<include resource="/prime-gui.xml" />
+	</StackedJoinable>
+</Framsticks>
Index: java/main/src/main/resources/prime-gui-experiment.xml
===================================================================
--- java/main/src/main/resources/prime-gui-experiment.xml	(revision 102)
+++ java/main/src/main/resources/prime-gui-experiment.xml	(revision 102)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Framsticks>
+	<include resource="/prime.xml" />
+	<include resource="/prime-gui.xml" />
+</Framsticks>
Index: java/main/src/main/resources/prime-gui.xml
===================================================================
--- java/main/src/main/resources/prime-gui.xml	(revision 101)
+++ java/main/src/main/resources/prime-gui.xml	(revision 102)
@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Framsticks>
-	<include resource="/prime.xml" />
 
 	<import class="com.framsticks.gui.Browser" />
@@ -8,4 +7,5 @@
 		<RemoteTree name="prime-experiment" address="localhost:9007" />
 		<RemoteTree name="worker" address="localhost:9100" />
+		<include resource="/common-columns.xml" />
 	</Browser>
 </Framsticks>
Index: java/main/src/main/resources/prime-servers.xml
===================================================================
--- java/main/src/main/resources/prime-servers.xml	(revision 102)
+++ java/main/src/main/resources/prime-servers.xml	(revision 102)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Framsticks>
+	<import class="com.framsticks.running.LoggingOutputListener" />
+	<import class="com.framsticks.running.FramsServer" />
+	<FramsServer name="frams" port="9100" expdef="prime">
+		<LoggingOutputListener />
+	</FramsServer>
+	<FramsServer name="frams" port="9101" expdef="prime">
+		<LoggingOutputListener />
+	</FramsServer>
+	<FramsServer name="frams" port="9102" expdef="prime">
+		<LoggingOutputListener />
+	</FramsServer>
+	<FramsServer name="frams" port="9103" expdef="prime">
+		<LoggingOutputListener />
+	</FramsServer>
+</Framsticks>
+
Index: java/main/src/main/resources/prime.xml
===================================================================
--- java/main/src/main/resources/prime.xml	(revision 101)
+++ java/main/src/main/resources/prime.xml	(revision 102)
@@ -3,26 +3,16 @@
 	<import class="com.framsticks.hosting.Server" />
 	<import class="com.framsticks.test.PrimeExperiment" />
-	<import class="com.framsticks.experiment.Simulator" />
+	<!-- <import class="com.framsticks.experiment.Simulator" /> -->
+	<import class="com.framsticks.experiment.SimulatorConnector" />
 	<import class="com.framsticks.core.LocalTree" />
-	<import class="com.framsticks.running.LoggingOutputListener" />
-	<import class="com.framsticks.running.FramsServer" />
 	<Server port="9007">
-		<LocalTree name="test">
-			<PrimeExperiment name="prime">
-				<Simulator address="localhost:9100"/>
-				<Simulator address="localhost:9101"/>
-				<Simulator address="localhost:9102"/>
+		<LocalTree name="prime-local-tree">
+			<PrimeExperiment>
+				<SimulatorConnector address="localhost:9100" />
+				<SimulatorConnector address="localhost:9101" />
+				<SimulatorConnector address="localhost:9102" />
 			</PrimeExperiment>
 		</LocalTree>
 	</Server>
-	<FramsServer name="frams" port="9100">
-		<LoggingOutputListener />
-	</FramsServer>
-	<FramsServer name="frams" port="9101">
-		<LoggingOutputListener />
-	</FramsServer>
-	<FramsServer name="frams" port="9102">
-		<LoggingOutputListener />
-	</FramsServer>
 </Framsticks>
 
Index: java/main/src/test/java/com/framsticks/core/ListChangeTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/core/ListChangeTest.java	(revision 101)
+++ java/main/src/test/java/com/framsticks/core/ListChangeTest.java	(revision 102)
@@ -7,5 +7,5 @@
 
 import com.framsticks.core.ListChange.Action;
-import com.framsticks.params.AccessOperations;
+import static com.framsticks.params.AccessOperations.*;
 import com.framsticks.params.FramsClass;
 import com.framsticks.params.ListSink;
@@ -40,5 +40,5 @@
 	public void testFramsClass() {
 		framsClass = FramsClass.build().forClass(ListChange.class);
-		assertThat(framsClass.getParamCount()).isEqualTo(3);
+		assertThat(framsClass.getParamCount()).isEqualTo(4);
 	}
 
@@ -60,6 +60,6 @@
 
 	@Test(dependsOnMethods = "createReflectionAccess")
-	public void load() throws Exception {
-		AccessOperations.load(access.select(listChange), ListSource.createFrom("type:2", "pos:0", "id:test"));
+	public void loading() throws Exception {
+		load(access.select(listChange), ListSource.createFrom("type:2", "pos:0", "id:test"));
 
 		assertThat(listChange.action).isEqualTo(Action.Modify);
@@ -68,5 +68,5 @@
 
 		ListSink sink = new ListSink();
-		access.select(listChange).save(sink);
+		save(access.select(listChange), sink);
 		assertThat(sink.getOut()).isEqualTo(Arrays.asList("ListChange:", "type:2", "pos:0", "id:test", ""));
 	}
Index: java/main/src/test/java/com/framsticks/gui/console/DirectConsoleTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/console/DirectConsoleTest.java	(revision 101)
+++ java/main/src/test/java/com/framsticks/gui/console/DirectConsoleTest.java	(revision 102)
@@ -20,12 +20,9 @@
 	protected Joinable createSubject() {
 
-		connection = new ClientSideRawConnection();
-		connection.setAddress(new Address("localhost:9009"));
-
-		console = new DirectConsole().setConnection(connection);
+		console = new DirectConsole().setAddress(new Address("localhost:9009"));
 		joinables = new JoinableCollection<>();
 		joinables.setObservableName("connection and console");
 		joinables.add(console);
-		joinables.add(connection);
+		joinables.add(console.getConnection());
 
 		return joinables;
Index: java/main/src/test/java/com/framsticks/test/MonitorBasedTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/MonitorBasedTest.java	(revision 101)
+++ java/main/src/test/java/com/framsticks/test/MonitorBasedTest.java	(revision 102)
@@ -30,5 +30,5 @@
 	}
 
-	@AfterClass(timeOut = 3000)
+	@AfterClass(timeOut = 30000)
 	public void tearDown() {
 		monitor.drop().join();
Index: java/main/src/test/java/com/framsticks/test/PrimeExperimentTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/PrimeExperimentTest.java	(revision 101)
+++ java/main/src/test/java/com/framsticks/test/PrimeExperimentTest.java	(revision 102)
@@ -6,15 +6,33 @@
 
 import com.framsticks.core.XmlBasedTest;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.StackedJoinable;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 @Test
 public class PrimeExperimentTest extends XmlBasedTest {
 
+	private static final Logger log = LogManager.getLogger(PrimeExperimentTest.class);
+
 	protected PrimeExperiment experiment;
+
 
 	@Test
 	public void start() {
+		log.debug("starting");
 		assertThat(framsticks).isNotNull();
-		assertThat(framsticks.get("prime")).isInstanceOf(PrimeExperiment.class);
-		experiment = (PrimeExperiment) framsticks.get("prime");
+		assertThat(framsticks.size()).isEqualTo(1);
+		assertThat(framsticks.get("stacked")).isInstanceOf(StackedJoinable.class);
+		StackedJoinable stacked = (StackedJoinable) framsticks.get("stacked");
+
+		assertThat(stacked.size()).isEqualTo(2);
+		assertThat(stacked.get(1)).isInstanceOf(PrimeExperiment.class);
+		// assertThat(framsticks.get("prime")).isInstanceOf(PrimeExperiment.class);
+		// experiment = (PrimeExperiment) framsticks.get("prime");
+		//
+		Dispatching.sleep(3);
 	}
+
 }
Index: java/main/src/test/java/com/framsticks/test/prime/PrimePackageTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/prime/PrimePackageTest.java	(revision 102)
+++ java/main/src/test/java/com/framsticks/test/prime/PrimePackageTest.java	(revision 102)
@@ -0,0 +1,25 @@
+package com.framsticks.test.prime;
+
+// import static org.fest.assertions.Assertions.*;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.test.TestConfiguration;
+
+@Test
+public class PrimePackageTest extends TestConfiguration {
+
+
+
+
+	@Test
+	public void printPrimePackage() {
+	}
+	// ExpParams:
+	// from_number:100
+	// to_number:200
+
+	// ExpState:
+	// current_number:201
+	// result:151,157,163,167,173,179,181,191,193,197,199
+}
Index: java/main/src/test/resources/configs/PrimeExperimentTest.xml
===================================================================
--- java/main/src/test/resources/configs/PrimeExperimentTest.xml	(revision 101)
+++ java/main/src/test/resources/configs/PrimeExperimentTest.xml	(revision 102)
@@ -3,5 +3,22 @@
 	<import class="com.framsticks.test.PrimeExperiment" />
 	<import class="com.framsticks.experiment.Simulator" />
-	<PrimeExperiment name="prime">
-	</PrimeExperiment>
+	<import class="com.framsticks.util.dispatching.StackedJoinable" />
+	<import class="com.framsticks.util.dispatching.JoinableCollection" />
+	<import class="com.framsticks.running.LoggingOutputListener" />
+	<import class="com.framsticks.running.FramsServer" />
+	<import class="com.framsticks.experiment.SimulatorConnector" />
+	<StackedJoinable interval="1">
+		<JoinableCollection name="servers">
+			<FramsServer name="frams" port="9100" expdef="prime">
+				<LoggingOutputListener />
+			</FramsServer>
+			<FramsServer name="frams" port="9101" expdef="prime">
+				<LoggingOutputListener />
+			</FramsServer>
+		</JoinableCollection>
+		<PrimeExperiment>
+			<SimulatorConnector address="localhost:9100" />
+			<SimulatorConnector address="localhost:9101" />
+		</PrimeExperiment>
+	</StackedJoinable>
 </Framsticks>
Index: java/main/src/test/resources/configs/ServerTest.xml
===================================================================
--- java/main/src/test/resources/configs/ServerTest.xml	(revision 101)
+++ java/main/src/test/resources/configs/ServerTest.xml	(revision 102)
@@ -6,9 +6,9 @@
 	<import class="com.framsticks.test.TestClass" />
 	<import class="com.framsticks.running.LoggingOutputListener" />
-	<Server port="9007">
+	<Server port="9006">
 		<LocalTree name="test">
 			<TestClass name="a test name" />
 		</LocalTree>
 	</Server>
-	<RemoteTree name="remote" address="localhost:9007" />
+	<RemoteTree name="remote" address="localhost:9006" />
 </Framsticks>
Index: java/main/src/test/resources/log4j2.xml
===================================================================
--- java/main/src/test/resources/log4j2.xml	(revision 101)
+++ java/main/src/test/resources/log4j2.xml	(revision 102)
@@ -7,6 +7,13 @@
 	</appenders>
 	<loggers>
-		<logger name="com.framsticks" level="warn" />
+		<logger name="com.framsticks" level="info" />
+		<logger name="com.framsticks.running.ExternalProcess" level="debug" />
 		<logger name="com.framsticks.test.TestConfiguration" level="info" />
+		<logger name="com.framsticks.experiment" level="debug" />
+		<logger name="com.framsticks.test.PrimeExperiment" level="debug" />
+		<!-- <logger name="com.framsticks.util.dispatching.AbstractJoinable" level="debug" /> -->
+		<!-- <logger name="com.framsticks.util.dispatching.AbstractJoinable.Report" level="info" /> -->
+		<!-- <logger name="com.framsticks.util.dispatching.Monitor" level="debug" /> -->
+		<!-- <logger name="com.framsticks.util.dispatching.StackedJoinable" level="debug" /> -->
 		<root level="info">
 			<appender-ref ref="Console"/>
