Index: /java/main/pom.xml
===================================================================
--- /java/main/pom.xml	(revision 95)
+++ /java/main/pom.xml	(revision 96)
@@ -147,5 +147,5 @@
 					<workingDirectory>/home/psniegowski/mgr/framsticks</workingDirectory>
 					<arguments>
-						<!-- <argument>-ea</argument> -->
+						<argument>-ea</argument>
 						<argument>-Xdebug</argument>
 						<argument>-Xrunjdwp:transport=dt_socket,address=4711,server=y,suspend=n</argument>
Index: /java/main/src/main/java/com/framsticks/communication/ClientConnection.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/ClientConnection.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/ClientConnection.java	(revision 96)
@@ -11,11 +11,13 @@
 import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.JoinableState;
 import com.framsticks.util.lang.Pair;
 import com.framsticks.util.lang.Strings;
+
+import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
 
 import java.io.IOException;
 import java.net.Socket;
-import java.net.SocketException;
 import java.util.*;
 import java.util.regex.Matcher;
@@ -39,31 +41,18 @@
 	}
 
+	public ClientConnection(String address) {
+		super(address, "client connection");
+		Matcher matcher = addressPattern.matcher(address);
+		if (!matcher.matches()) {
+			log.fatal("invalid address: " + address);
+			hostName = null;
+			port = 0;
+			return;
+		}
+		hostName = matcher.group(1);
+		port = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 9009;
+	}
 
 	protected StateFunctor connectedFunctor;
-
-	@Override
-	protected void joinableStart() {
-		try {
-			log.debug("connecting to " + address);
-
-			socket = new Socket(hostName, port);
-
-			socket.setSoTimeout(500);
-
-			log.debug("connected to " + hostName + ":" + port);
-			connected = true;
-			runThreads();
-
-			connectedFunctor.call(null);
-		} catch (SocketException e) {
-			log.error("failed to connect: " + e);
-			connectedFunctor.call(e);
-		} catch (IOException e) {
-			log.error("buffer creation failure");
-			connectedFunctor.call(e);
-			// close();
-		}
-	}
-
 
 	private static abstract class InboundMessage {
@@ -78,4 +67,5 @@
 			currentFilePath = path;
 		}
+
 		protected void finishCurrentFile() {
 			if (currentFileContent == null) {
@@ -84,13 +74,13 @@
 			files.add(new File(currentFilePath, new ListSource(currentFileContent)));
 			currentFilePath = null;
-			currentFileContent= null;
+			currentFileContent = null;
 		}
 
 		public abstract void startFile(String path);
 
-		public void addLine(String line) {
+		public final void addLine(String line) {
 			assert line != null;
 			assert currentFileContent != null;
-			currentFileContent.add(line.substring(0, line.length() - 1));
+			currentFileContent.add(line);
 		}
 
@@ -127,12 +117,14 @@
 		public void startFile(String path) {
 			finishCurrentFile();
-			if (path == null) {
+			if (!Strings.notEmpty(path)) {
 				assert request instanceof ApplicationRequest;
-				path = ((ApplicationRequest)request).getPath();
-			}
+				path = ((ApplicationRequest) request).getPath();
+			}
+			Strings.assureNotEmpty(path);
 			initCurrentFile(path);
 		}
 
 		public void eof() {
+			assert Strings.notEmpty(currentFilePath);
 			finishCurrentFile();
 			//no-operation
@@ -153,6 +145,6 @@
 		}
 	}
+
 	private Map<Integer, SentQuery<?>> queryMap = new HashMap<>();
-
 
 	protected final String hostName;
@@ -161,19 +153,6 @@
 	private static Pattern addressPattern = Pattern.compile("^([^:]*)(:([0-9]+))?$");
 
-	public ClientConnection(String address) {
-		super(address);
-		Matcher matcher = addressPattern.matcher(address);
-		if (!matcher.matches()) {
-			log.fatal("invalid address: " + address);
-			hostName = null;
-			port = 0;
-			return;
-		}
-		hostName = matcher.group(1);
-		port = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 9009;
-	}
 
 	private SentQuery<?> currentlySentQuery;
-
 
 	public <C extends Connection> void send(Request request, ResponseCallback<C> callback) {
@@ -184,8 +163,9 @@
 	public <C> void send(Request request, Dispatcher<C> dispatcher, ResponseCallback<? extends C> callback) {
 
-		if (!isConnected()) {
+		if (getState().ordinal() > JoinableState.RUNNING.ordinal()) {
 			log.fatal("not connected");
 			return;
 		}
+
 		final SentQuery<C> sentQuery = new SentQuery<C>();
 		sentQuery.request = request;
@@ -193,5 +173,5 @@
 		sentQuery.dispatcher = dispatcher;
 
-		senderThread.dispatch(new RunAt<Connection>(){
+		senderThread.dispatch(new RunAt<Connection>() {
 			@Override
 			public void run() {
@@ -220,8 +200,10 @@
 					message.append(" ").append(id);
 				}
+				message.append(" ");
 				sentQuery.request.construct(message);
 				String out = message.toString();
 
 				output.println(out);
+				output.flush();
 				log.debug("sending query: " + out);
 
@@ -234,7 +216,6 @@
 			notifyAll();
 		}
-		*/
-	}
-
+		 */
+	}
 
 	@Override
@@ -272,33 +253,25 @@
 	}
 
-	public void sendQueryVersion(final int version, final StateFunctor stateFunctor) {
-		send(new VersionRequest().version(version), new StateCallback<Connection>() {
+	public void sendQueryVersion(final int version, StateFunctor stateFunctor) {
+		send(new VersionRequest().version(version), new StateCallback<Connection>(stateFunctor) {
 			@Override
-			public void call(Exception e) {
-				if (e != null) {
-					log.fatal("failed to upgrade protocol to version: " + version);
-					return;
-				}
+			public void callImpl() {
 				protocolVersion = version;
 				if (version < 4) {
 					/** it is an implicit loop here*/
-					sendQueryVersion(version + 1, stateFunctor);
+					sendQueryVersion(version + 1, move());
 					return;
 				}
-				send(new UseRequest().feature("request_id"), new StateCallback<Connection>() {
+				send(new UseRequest().feature("request_id"), new StateCallback<Connection>(move()) {
 					@Override
-					public void call(Exception e) {
-						requestIdEnabled = e == null;
-						/*
-						synchronized (ClientConnection.this) {
-							ClientConnection.this.notifyAll();
-						}
-						*/
-						if (!requestIdEnabled) {
-							log.fatal("protocol negotiation failed");
-							stateFunctor.call(new Exception("protocol negotiation failed", e));
-							return;
-						}
-						stateFunctor.call(null);
+					public void handle(FramsticksException exception) {
+						requestIdEnabled = false;
+						log.fatal("protocol negotiation failed");
+						super.handle(new FramsticksException().msg("protocol negotiation failed").cause(exception));
+					}
+
+					@Override
+					public void callImpl() {
+						requestIdEnabled = true;
 					}
 				});
@@ -307,5 +280,4 @@
 		});
 	}
-
 
 	private synchronized SentQuery<?> fetchQuery(Integer id, boolean remove) {
@@ -348,5 +320,5 @@
 
 	protected void processEvent(String rest) {
-		Matcher matcher = eventPattern.matcher(rest);
+		Matcher matcher = Request.EVENT_PATTERN.matcher(rest);
 		if (!matcher.matches()) {
 			log.error("invalid event line: " + rest);
@@ -363,40 +335,64 @@
 	}
 
-
 	protected void processMessageStartingWith(String line) {
-		Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
-		if (command.first.equals("event")) {
-			processEvent(command.second);
-			return;
-		}
-		Pair<Integer, String> rest = parseRest(command.second);
-
-		if (command.first.equals("file")) {
-			SentQuery<?> sentQuery = fetchQuery(rest.first, false);
-			sentQuery.startFile(rest.second);
-			processMessage(sentQuery);
-			return;
-		}
-
-		SentQuery<?> sentQuery = fetchQuery(rest.first, true);
-		if (sentQuery == null) {
-			return;
-		}
-		log.debug("parsing response for request " + sentQuery);
-
-		sentQuery.dispatchResponseProcess(new Response(command.first.equals("ok"), rest.second, sentQuery.getFiles()));
+		try {
+			Pair<CharSequence, CharSequence> command = Request.takeIdentifier(line);
+			if (command.first.equals("event")) {
+				processEvent(command.second.toString());
+				return;
+			}
+			Pair<Integer, CharSequence> rest = takeRequestId(command.second);
+
+			if (command.first.equals("file")) {
+				SentQuery<?> sentQuery = fetchQuery(rest.first, false);
+				sentQuery.startFile(rest.second.toString());
+				processMessage(sentQuery);
+				return;
+			}
+
+			SentQuery<?> sentQuery = fetchQuery(rest.first, true);
+			if (sentQuery == null) {
+				return;
+			}
+			log.debug("parsing response for request " + sentQuery);
+
+			sentQuery.dispatchResponseProcess(new Response(command.first.equals("ok"), rest.second.toString(), sentQuery.getFiles()));
+		} catch (FramsticksException e) {
+			throw new FramsticksException().msg("failed to process message").arg("starting with line", line).cause(e);
+		}
 	}
 
 	@Override
 	protected void receiverThreadRoutine() {
-		while (connected) {
+		while (isRunning() && !isConnected()) {
+			log.debug("connecting to " + address);
+			try {
+				socket = new Socket(hostName, port);
+			} catch (IOException e) {
+				log.info(this + " failed to connect (retrying): " + e);
+				Dispatching.sleep(0.5);
+			}
+		}
+
+		log.debug(this + " connected");
+		try {
+			socket.setSoTimeout(500);
+			setupStreams();
+		} catch (Exception e) {
+			throw new FramsticksException().msg("failed to initialize socket").cause(e).arg("connection", this);
+		}
+
+		connectedFunctor.call();
+
+		while (isRunning() && isConnected()) {
 			try {
 				processMessageStartingWith(getLine());
 			} catch (Exception e) {
+				log.log(isRunning() ? Level.ERROR : Level.DEBUG, "caught exception: ", e);
 				break;
 			}
 		}
-	}
-
-
+		interrupt();
+		finish();
+	}
 }
Index: /java/main/src/main/java/com/framsticks/communication/Connection.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 96)
@@ -12,6 +12,4 @@
 import java.net.Socket;
 import java.net.SocketTimeoutException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import com.framsticks.util.dispatching.AbstractJoinable;
@@ -33,6 +31,4 @@
 	protected Socket socket = null;
 
-	protected volatile boolean connected = false;
-
 	public boolean requestIdEnabled = false;
 
@@ -43,35 +39,48 @@
 	}
 	protected final String address;
+	protected final String description;
 
 	protected final Thread<Connection> senderThread = new Thread<>();
 	protected final Thread<Connection> receiverThread = new Thread<>();
-	protected final JoinableCollection<Thread<Connection>> threads = new JoinableCollection<>(true);
+	protected final JoinableCollection<Thread<Connection>> threads = new JoinableCollection<>();
+
+	protected void setUpThreadNames(String name) {
+	}
 
 	/**
 	 *
 	 */
-	public Connection(String address) {
+	public Connection(String address, String description) {
 		this.address = address;
+		this.description = description;
+		threads.setObservableName(address + " connection threads");
 		threads.add(senderThread);
 		threads.add(receiverThread);
-	}
-	public boolean isConnected() {
-		return connected;
-	}
-
-
-	protected static final String ARGUMENT_PATTERN_FRAGMENT = "((?:\\S+)|(?:\"[^\"]*\"))";
-	protected static final Pattern requestIdEnabledPattern = Pattern.compile("^\\s*([0-9]+)(?:\\s+" + ARGUMENT_PATTERN_FRAGMENT + ")?\\n$");
-	protected static final Pattern requestIDisabledPattern = Pattern.compile("^\\s*" + ARGUMENT_PATTERN_FRAGMENT + "?\\n$");
-	protected static final Pattern eventPattern = Pattern.compile("^\\s*(\\S+)\\s*(\\S+)\\n");
-
-
-	protected final Pair<Integer, String> parseRest(String rest) {
-		Matcher matcher = (requestIdEnabled ? requestIdEnabledPattern : requestIDisabledPattern).matcher(rest);
-		if (!matcher.matches()) {
-			log.fatal("unmatched first line of input: " + rest);
-			return null;
-		}
-		return new Pair<Integer, String>(requestIdEnabled ? Integer.parseInt(matcher.group(1)) : null, matcher.group(requestIdEnabled ? 2 : 1));
+
+		senderThread.setName(description + " thread " + address + " sender");
+		receiverThread.setName(description + " thread " + address + " receiver");
+	}
+
+	public synchronized boolean isConnected() {
+		return socket != null && socket.isConnected();
+	}
+
+
+	// protected static final String ARGUMENT_PATTERN_FRAGMENT = "((?:\\S+)|(?:\\\"[^\"]*\\\"))";
+	// protected static final Pattern REQUEST_ID_ENABLED_PATTERN = Pattern.compile("^\\s*([0-9]+)(?:\\s+" + ARGUMENT_PATTERN_FRAGMENT + ")?$");
+	// protected static final Pattern REQUEST_ID_DISABLED_PATTERN = Pattern.compile("^\\s*" + ARGUMENT_PATTERN_FRAGMENT + "?$");
+
+	// // protected final Pair<String, String> breakLine(String line)
+	// protected final Pair<Integer, String> parseRest(String rest) {
+	// 	Matcher matcher = (requestIdEnabled ? REQUEST_ID_ENABLED_PATTERN : REQUEST_ID_DISABLED_PATTERN).matcher(rest);
+	// 	if (!matcher.matches()) {
+	// 		log.fatal("unmatched first line of input: '" + rest + "'");
+	// 		return null;
+	// 	}
+	// 	return new Pair<Integer, String>(requestIdEnabled ? Integer.parseInt(matcher.group(1)) : null, matcher.group(requestIdEnabled ? 2 : 1));
+	// }
+
+	protected final Pair<Integer, CharSequence> takeRequestId(CharSequence line) {
+		return Request.takeRequestId(requestIdEnabled, line);
 	}
 
@@ -81,8 +90,8 @@
 	int iterator = 0;
 	int bufferStart = 0;
-	char[] readBuffer = new char[BUFFER_LENGTH];
+	final char[] readBuffer = new char[BUFFER_LENGTH];
 
 	protected String getLine() {
-		StringBuilder lineBuffer = new StringBuilder();
+		final StringBuilder lineBuffer = new StringBuilder();
 		try {
 			while (!Thread.interrupted()) {
@@ -92,10 +101,16 @@
 						continue;
 					}
-					lineBuffer.append(readBuffer, bufferStart, iterator - bufferStart + 1);
+					/** Do not append new line. */
+					lineBuffer.append(readBuffer, bufferStart, iterator - bufferStart);
 					++iterator;
 					bufferStart = iterator;
 					return lineBuffer.toString();
 				}
-				lineBuffer.append(readBuffer, bufferStart, readChars - bufferStart);
+				final int length = readChars - bufferStart;
+				if (length > 0) {
+					assert bufferStart >= 0 && bufferStart < BUFFER_LENGTH;
+					assert bufferStart + length <= BUFFER_LENGTH;
+					lineBuffer.append(readBuffer, bufferStart, length);
+				}
 
 				readChars = 0;
@@ -118,28 +133,15 @@
 	protected abstract void receiverThreadRoutine();
 
-	protected void setUpThread(Thread<Connection> thread, String name) {
-		thread.setName("connection thread " + address + " " + name);
-	}
-
-	protected void runThreads() {
+
+	protected void setupStreams() {
 		try {
 			output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), Encoding.getFramsticksCharset()), true);
 			input = new BufferedReader(new InputStreamReader(socket.getInputStream(), Encoding.getFramsticksCharset()));
+			synchronized (this) {
+				this.notifyAll();
+			}
 		} catch (IOException e) {
-			log.error("buffer creation failure");
-			return;
+			throw new FramsticksException().msg("failed to setup streams").cause(e).arg("connection", this);
 		}
-
-		setUpThread(senderThread, "sender");
-		setUpThread(receiverThread, "receiver");
-		Dispatching.use(threads, this);
-
-		receiverThread.dispatch(new RunAt<Connection>() {
-			@Override
-			public void run() {
-				receiverThreadRoutine();
-			}
-		});
-
 	}
 
@@ -153,13 +155,4 @@
 	}
 
-	@Override
-	protected void joinableInterrupt() {
-		protocolVersion = -1;
-
-		connected = false;
-		Dispatching.drop(threads, this);
-
-		// finish();
-	}
 
 	@Override
@@ -193,7 +186,42 @@
 
 	@Override
+	public String getName() {
+		return description + " " + address;
+	}
+
+	@Override
+	protected void joinableStart() {
+		Dispatching.use(threads, this);
+
+		senderThread.dispatch(new RunAt<Connection>() {
+			@Override
+			public void run() {
+				synchronized (Connection.this) {
+					while (state.equals(JoinableState.RUNNING) && output == null) {
+						Dispatching.wait(Connection.this, 500);
+					}
+				}
+			}
+		});
+
+		receiverThread.dispatch(new RunAt<Connection>() {
+			@Override
+			public void run() {
+				receiverThreadRoutine();
+			}
+		});
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		protocolVersion = -1;
+		Dispatching.drop(threads, this);
+		finish();
+	}
+
+
+	@Override
 	protected void joinableJoin() throws InterruptedException {
 		Dispatching.join(threads);
-
 	}
 
Index: /java/main/src/main/java/com/framsticks/communication/File.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/File.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/File.java	(revision 96)
@@ -1,5 +1,11 @@
 package com.framsticks.communication;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
 import com.framsticks.params.SourceInterface;
+// import com.framsticks.util.lang.Strings;
 
 /**
@@ -7,18 +13,25 @@
  */
 public final class File {
-    protected final String path;
-    protected final SourceInterface content;
+	protected final String path;
+	protected final SourceInterface content;
 
-    public File(String path, SourceInterface content) {
-        this.path = path;
-        this.content = content;
-    }
+	public File(@Nonnull String path, @Nonnull SourceInterface content) {
+		// assert Strings.notEmpty(path);
+		this.path = path;
+		this.content = content;
+	}
 
-    public String getPath() {
-        return path;
-    }
+	public String getPath() {
+		return path;
+	}
 
-    public SourceInterface getContent() {
-        return content;
-    }
+	public SourceInterface getContent() {
+		return content;
+	}
+
+	public static List<File> single(File file) {
+		List<File> result = new ArrayList<File>();
+		result.add(file);
+		return result;
+	}
 }
Index: /java/main/src/main/java/com/framsticks/communication/Request.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/Request.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/Request.java	(revision 96)
@@ -1,5 +1,10 @@
 package com.framsticks.communication;
 
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import com.framsticks.communication.queries.*;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.lang.Pair;
 
 /**
@@ -8,4 +13,11 @@
 public abstract class Request {
 
+	public abstract String getCommand();
+
+	protected abstract StringBuilder construct(StringBuilder buffer);
+
+
+
+
 	public static void quoteValue(StringBuilder builder, String value) {
 		String quote = ((value.indexOf(' ') > 0) || (value.length() == 0) ? "\"" : "");
@@ -13,39 +25,92 @@
 	}
 
-	public abstract String getCommand();
-
-	protected abstract StringBuilder construct(StringBuilder buffer);
-	//private static Pattern queryPattern = Pattern.compile("^(\\S+)\\s+(\\S+)(?:\\s+(\\S+))?$");
+	public static Request parse(CharSequence type, CharSequence rest) {
+		final Request request = Request.createRequestByTypeString(type.toString());
+		request.parseRest(rest);
+		return request;
+	}
 
 	public static Request createRequestByTypeString(String type) {
-		if (type.equals("get")) {
-			return new GetRequest();
+		switch (type) {
+			case "get": return new GetRequest();
+			case "set": return new SetRequest();
+			case "info": return new InfoRequest();
+			case "call": return new CallRequest();
+			case "reg": return new RegistrationRequest();
+			case "use": return new UseRequest();
+			case "version": return new VersionRequest();
 		}
-		if (type.equals("set")) {
-			return new SetRequest();
-		}
-		if (type.equals("info")) {
-			return new InfoRequest();
-		}
-		if (type.equals("call")) {
-			return new CallRequest();
-		}
-		if (type.equals("reg")) {
-			return new RegistrationRequest();
-		}
-		if (type.equals("use")) {
-			return new UseRequest();
-		}
-		if (type.equals("version")) {
-			return new VersionRequest();
-		}
-		return null;
+		throw new FramsticksException().msg("unknown request type").arg("type", type);
 	}
 
-	public abstract void parseRest(String rest);
+	public abstract CharSequence parseRest(CharSequence rest);
 
 	@Override
 	public String toString() {
-		return construct(new StringBuilder().append(getCommand())).toString();
+		return getCommand() + " request";
 	}
+
+	public String stringRepresentation() {
+		return construct(new StringBuilder().append(getCommand()).append(" ")).toString();
+	}
+
+	public static final Pattern EVENT_PATTERN = Pattern.compile("^\\s*(\\S+)\\s*(\\S+)");
+
+	public static final Pattern STRING_BREAKER_PATTERN = Pattern.compile("^\\s*(?:(?:\\\"([^\"]*)\\\")|([^ ]+))\\s*(.*)$");
+	public static final Pattern IDENTIFIER_BREAKER_PATTERN = Pattern.compile("^\\s*([^ ]+)\\s*(.*)$");
+
+	// public static Matcher match(Pattern pattern, CharSequence line) {
+	// 	Matcher matcher = pattern.matcher(line);
+	// 	if (!matcher.matches()) {
+	// 		return null;
+	// 		// throw new FramsticksException().msg("failed to take").arg("pattern", pattern).arg("line", line);
+	// 	}
+	// 	return matcher;
+	// }
+
+	public static Pair<CharSequence, CharSequence> takeIdentifier(CharSequence line) {
+		Matcher matcher = IDENTIFIER_BREAKER_PATTERN.matcher(line);
+		if (!matcher.matches()) {
+			return null;
+		}
+		return new Pair<CharSequence, CharSequence>(line.subSequence(matcher.start(1), matcher.end(1)), line.subSequence(matcher.start(2), matcher.end(2)));
+	}
+
+	public static CharSequence takeGroup(CharSequence input, Matcher matcher, int group) {
+		// return (matcher.start(group) == matcher.end(group)) ? null : input.subSequence(matcher.start(group), matcher.end(group));
+		return input.subSequence(matcher.start(group), matcher.end(group));
+	}
+
+	public static Pair<CharSequence, CharSequence> takeString(CharSequence line) {
+		Matcher matcher = STRING_BREAKER_PATTERN.matcher(line);
+		if (!matcher.matches()) {
+			return null;
+		}
+		assert ((matcher.start(1) == -1) != (matcher.start(2) == -1));
+		return new Pair<CharSequence, CharSequence>(takeGroup(line, matcher, (matcher.start(1) != -1 ? 1 : 2)), takeGroup(line, matcher, 3));
+	}
+
+	protected static final Pattern REQUEST_ID_BREAKER_PATTERN = Pattern.compile("^\\s*([0-9]+)\\s*(.*)$");
+
+	protected final static Pair<Integer, CharSequence> takeRequestId(boolean withId, CharSequence line) {
+		if (withId) {
+			Matcher matcher = REQUEST_ID_BREAKER_PATTERN.matcher(line);
+			if (!matcher.matches()) {
+				return null;
+			}
+			return new Pair<Integer, CharSequence>(Integer.valueOf(takeGroup(line, matcher, 1).toString()), takeGroup(line, matcher, 2));
+		}
+		return new Pair<Integer, CharSequence>(null, line);
+	}
+
+	public static StringBuilder quoteArgumentIfNeeded(StringBuilder builder, Object argument) {
+		String r = argument.toString();
+		if (r.indexOf(' ') != -1) {
+			builder.append('"').append(r).append('"');
+		} else {
+			builder.append(r);
+		}
+		return builder;
+	}
+
 }
Index: /java/main/src/main/java/com/framsticks/communication/Response.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/Response.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/Response.java	(revision 96)
@@ -7,28 +7,28 @@
  */
 public class Response {
-    protected final boolean ok;
-    protected final String comment;
-    protected final List<File> files;
+	protected final boolean ok;
+	protected final String comment;
+	protected final List<File> files;
 
-    public Response(boolean ok, String comment, List<File> files) {
-        this.ok = ok;
-        this.comment = comment;
-        this.files = files;
-    }
+	public Response(boolean ok, String comment, List<File> files) {
+		this.ok = ok;
+		this.comment = comment;
+		this.files = files;
+	}
 
-    public final String getComment() {
-        return comment;
-    }
+	public final String getComment() {
+		return comment;
+	}
 
-    public final boolean getOk() {
-        return ok;
-    }
+	public final boolean getOk() {
+		return ok;
+	}
 
-    public final List<File> getFiles() {
-        return files;
-    }
+	public final List<File> getFiles() {
+		return files;
+	}
 
-    public final boolean hasFiles() {
-        return files != null && !files.isEmpty();
-    }
+	public final boolean hasFiles() {
+		return files != null && !files.isEmpty();
+	}
 }
Index: /java/main/src/main/java/com/framsticks/communication/ResponseCallback.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/ResponseCallback.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/ResponseCallback.java	(revision 96)
@@ -1,8 +1,17 @@
 package com.framsticks.communication;
+
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 
 /**
  * @author Piotr Sniegowski
  */
-public interface ResponseCallback<C> {
-	public void process(Response response);
+public abstract class ResponseCallback<C> implements ExceptionResultHandler {
+	public abstract void process(Response response);
+
+	@Override
+	public void handle(FramsticksException e) {
+		process(new Response(false, e.getMsg(), null));
+	}
+
 }
Index: /java/main/src/main/java/com/framsticks/communication/ServerConnection.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/ServerConnection.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/ServerConnection.java	(revision 96)
@@ -3,6 +3,10 @@
 import com.framsticks.communication.queries.*;
 import com.framsticks.params.SourceInterface;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.lang.Holder;
 import com.framsticks.util.lang.Pair;
 import com.framsticks.util.lang.Strings;
+
+import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
 
@@ -20,21 +24,24 @@
 
 	public ServerConnection(Socket socket, RequestHandler requestHandler) {
-		super("todo");
+		super(socket.getInetAddress().getHostAddress(), "server connection");
 		this.socket = socket;
 		this.requestHandler = requestHandler;
-		connected = true;
-
+		// socket.setSoTimeout(500);
+		setupStreams();
 	}
 
-	@Override
-	public String toString() {
-		return socket.getInetAddress().getHostAddress();
-	}
 
 	@Override
 	protected void receiverThreadRoutine() {
-		while (connected) {
-			processNextRequest();
+		while (isRunning() && isConnected()) {
+			try {
+				processNextRequest();
+			} catch (Exception e) {
+				log.log((isRunning() ? Level.ERROR : Level.DEBUG), "caught exception: ", e);
+				break;
+			}
 		}
+		interrupt();
+		finish();
 	}
 
@@ -85,6 +92,7 @@
 				output.print(outId);
 				if (Strings.notEmpty(response.getComment())) {
-					output.print(' ');
+					output.print(" \"");
 					output.print(response.getComment());
+					output.print('"');
 				}
 				output.print('\n');
@@ -96,34 +104,30 @@
 
 	protected void processNextRequest() {
-		String line = getLine();
-		Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
-		final Pair<Integer, String> rest = parseRest(command.second);
-		if (rest == null) {
-			respond(new Response(false, "\"invalid input\"", null), null);
+		final Holder<Integer> id = new Holder<>();
+		final String line = getLine();
+		try {
+			Pair<CharSequence, CharSequence> command = Request.takeIdentifier(line);
+			final Pair<Integer, CharSequence> rest = takeRequestId(command.second);
+			id.set(rest.first);
+
+			final Request request = Request.parse(command.first, rest.second);
+
+			if (log.isTraceEnabled()) {
+				log.trace("read request: " + request);
+			}
+
+			handleRequest(request, new ResponseCallback<ServerConnection>() {
+				@Override
+				public void process(Response response) {
+					respond(response, rest.first);
+				}
+			});
+		} catch (FramsticksException e) {
+			e.arg("id", id.get()).arg("line", line);
+			log.error("error: ", e);
+			respond(new Response(false, "invalid input: " + e.getMsg(), null), id.get());
 			return;
 		}
 
-		final Request request = Request.createRequestByTypeString(command.first);
-		if (request == null) {
-			respond(new Response(false, "\"invalid input\"", null), null);
-			return;
-		}
-		request.parseRest(rest.second);
-		if (log.isTraceEnabled()) {
-			log.trace("read request: " + request);
-		}
-
-		handleRequest(request, new ResponseCallback<ServerConnection>() {
-			@Override
-			public void process(Response response) {
-				respond(response, rest.first);
-			}
-		});
-	}
-
-	@Override
-	protected void joinableStart() {
-		// TODO Auto-generated method stub
-
 	}
 }
Index: /java/main/src/main/java/com/framsticks/communication/StateCallback.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/StateCallback.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/StateCallback.java	(revision 96)
@@ -1,4 +1,5 @@
 package com.framsticks.communication;
 
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.StateFunctor;
 
@@ -6,8 +7,55 @@
  * @author Piotr Sniegowski
  */
-public abstract class StateCallback<C> implements ResponseCallback<C>, StateFunctor {
+public abstract class StateCallback<C> extends ResponseCallback<C> implements StateFunctor {
+
+
+	protected StateFunctor wrapped;
+
+	public StateCallback(StateFunctor wrapped) {
+		this.wrapped = wrapped;
+	}
+
+	public StateCallback() {
+		this.wrapped = null;
+	}
+
+	protected StateFunctor move() {
+		assert wrapped != null;
+		StateFunctor result = wrapped;
+		wrapped = null;
+		return result;
+	}
+
+	protected abstract void callImpl();
+
+	@Override
+	public final void call() {
+		try {
+			callImpl();
+		} catch (FramsticksException e) {
+			handle(e);
+			return;
+		}
+		if (wrapped != null) {
+			wrapped.call();
+		}
+	}
+
+	@Override
+	public void handle(FramsticksException exception) {
+		if (wrapped != null) {
+			wrapped.handle(exception);
+			return;
+		}
+		throw exception;
+	}
+
 	@Override
 	public void process(Response response) {
-		call(response.getOk() ? null : new Exception(response.getComment()));
+		if (response.getOk()) {
+			call();
+		} else {
+			handle(new FramsticksException().msg("non-ok response").arg("comment", response.getComment()));
+		}
 	}
 }
Index: /java/main/src/main/java/com/framsticks/communication/Subscription.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/Subscription.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/Subscription.java	(revision 96)
@@ -7,4 +7,5 @@
 import com.framsticks.util.dispatching.Dispatching;
 import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.StateFunctor;
 import org.apache.log4j.Logger;
@@ -52,10 +53,10 @@
 				if (!response.getOk()) {
 					log.error("failed to unsunscribe " + this + ": " + response.getComment());
-					stateFunctor.call(new Exception(response.getComment()));
+					stateFunctor.handle(new FramsticksException().msg("unsubscription failed").arg("comment", response.getComment()));
 					return;
 				}
 				assert response.hasFiles();
 				log.debug("unsunscribed " + this);
-				stateFunctor.call(null);
+				stateFunctor.call();
 			}
 		});
Index: /java/main/src/main/java/com/framsticks/communication/queries/ApplicationRequest.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/queries/ApplicationRequest.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/queries/ApplicationRequest.java	(revision 96)
@@ -2,7 +2,7 @@
 
 import com.framsticks.communication.Request;
-import com.framsticks.util.lang.Delimeted;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
 
-import java.util.Collection;
 
 /**
@@ -12,25 +12,10 @@
 
 	protected String path;
-	protected String fields;
 
 	public ApplicationRequest path(String path) {
-		assert path != null;
+		Strings.assureNotEmpty(path);
 		this.path = path;
 		return this;
 	}
-
-	public ApplicationRequest field(String field) {
-		this.fields = field;
-		return this;
-	}
-
-	public ApplicationRequest fields(Collection<String> fields) {
-		Delimeted d = new Delimeted(",", "");
-		for (String f : fields) {
-			d.append(f);
-		}
-		return field(d.build());
-	}
-
 
 	public String getPath() {
@@ -38,16 +23,15 @@
 	}
 
+
 	@Override
 	protected StringBuilder construct(StringBuilder buffer) {
-		buffer.append(' ').append(path);
-		if (fields != null) {
-			buffer.append(' ').append(fields);
-		}
-		return buffer;
+		return buffer.append(path);
 	}
 
 	@Override
-	public void parseRest(String rest) {
-		path = rest;
+	public CharSequence parseRest(CharSequence rest) {
+		final Pair<CharSequence, CharSequence> p = takeIdentifier(rest);
+		path = p.first.toString();
+		return p.second;
 	}
 
Index: /java/main/src/main/java/com/framsticks/communication/queries/CallRequest.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/queries/CallRequest.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/queries/CallRequest.java	(revision 96)
@@ -1,6 +1,9 @@
 package com.framsticks.communication.queries;
 
-import com.framsticks.communication.Request;
+import com.framsticks.util.Misc;
+import com.framsticks.util.lang.Pair;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
@@ -10,23 +13,42 @@
 public class CallRequest extends ApplicationRequest {
 
-	protected String arguments;
-	protected String method;
+	protected final List<Object> arguments = new ArrayList<>();
+	protected String procedure;
 
-	public CallRequest setArguments(String arguments) {
-		this.arguments = arguments;
+	public CallRequest addArguments(String arguments) {
+		// this.arguments = arguments;
 		return this;
 	}
 
-	public CallRequest setArguments(List<String> arguments) {
-		StringBuilder buffer = new StringBuilder();
-		for (String a : arguments) {
-			buffer.append(" ");
-			Request.quoteValue(buffer, a.trim());
-		}
-		return this.setArguments(buffer.toString());
+	/**
+	 * @return the arguments
+	 */
+	public List<Object> getArguments() {
+		return arguments;
 	}
 
-	public CallRequest setMethod(String method) {
-		this.method = method;
+	/**
+	 * @return the procedure
+	 */
+	public String getProcedure() {
+		return procedure;
+	}
+
+	/**
+	 * @param arguments the arguments to set
+	 */
+	public CallRequest arguments(Collection<Object> arguments) {
+		this.arguments.clear();
+		this.arguments.addAll(arguments);
+		return this;
+	}
+
+	public CallRequest argument(Object argument) {
+		arguments.add(argument);
+		return this;
+	}
+
+	public CallRequest procedure(String procedure) {
+		this.procedure = procedure;
 		return this;
 	}
@@ -35,9 +57,9 @@
 	protected StringBuilder construct(StringBuilder buffer) {
 		super.construct(buffer);
-		if (method != null) {
-			buffer.append(" ").append(method);
-		}
-		if (arguments != null) {
-			buffer.append(arguments);
+		Misc.throwIfNull(procedure);
+		buffer.append(' ').append(procedure);
+		for (Object arg : arguments) {
+			buffer.append(' ');
+			quoteArgumentIfNeeded(buffer, arg);
 		}
 		return buffer;
@@ -49,3 +71,14 @@
 	}
 
+	@Override
+	public CharSequence parseRest(CharSequence rest) {
+		rest = super.parseRest(rest);
+		Pair<CharSequence, CharSequence> p = Misc.throwIfNull(takeIdentifier(rest));
+		this.procedure = p.first.toString();
+		while ((p = takeString(p.second)) != null) {
+			arguments.add(p.first);
+		}
+		return null;
+	}
+
 }
Index: /java/main/src/main/java/com/framsticks/communication/queries/GetRequest.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/queries/GetRequest.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/queries/GetRequest.java	(revision 96)
@@ -1,3 +1,9 @@
 package com.framsticks.communication.queries;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.framsticks.util.lang.Delimeted;
+import com.framsticks.util.lang.Pair;
 
 /**
@@ -5,5 +11,19 @@
  */
 public class GetRequest extends ApplicationRequest {
+	protected final List<String> fields = new ArrayList<>();
+
 	public GetRequest() {
+	}
+
+	public GetRequest fields(List<String> fields) {
+		this.fields.clear();
+		this.fields.addAll(fields);
+		return this;
+	}
+
+	public GetRequest field(String field) {
+		this.fields.clear();
+		this.fields.add(field);
+		return this;
 	}
 
@@ -12,3 +32,31 @@
 		return "get";
 	}
+
+	@Override
+	protected StringBuilder construct(StringBuilder buffer) {
+		super.construct(buffer);
+		if (!fields.isEmpty()) {
+			buffer.append(' ').append(new Delimeted<String>(",", "").append(fields.iterator()));
+		}
+		return buffer;
+	}
+
+	/**
+	 * @return the fields
+	 */
+	public List<String> getFields() {
+		return fields;
+	}
+
+	@Override
+	public CharSequence parseRest(CharSequence rest) {
+		rest = super.parseRest(rest);
+		Pair<CharSequence, CharSequence> p = takeIdentifier(rest);
+		if (p != null) {
+			for (String a : p.first.toString().split(",")) {
+				fields.add(a);
+			}
+		}
+		return null;
+	}
 }
Index: /java/main/src/main/java/com/framsticks/communication/queries/SetRequest.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/queries/SetRequest.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/queries/SetRequest.java	(revision 96)
@@ -1,3 +1,5 @@
 package com.framsticks.communication.queries;
+
+import com.framsticks.util.lang.Pair;
 
 /**
@@ -5,7 +7,14 @@
  */
 public class SetRequest extends ApplicationRequest {
+
+	protected String field;
 	protected String value;
 
 	public SetRequest() {
+	}
+
+	public SetRequest field(String field) {
+		this.field = field;
+		return this;
 	}
 
@@ -17,13 +26,35 @@
 	@Override
 	protected StringBuilder construct(StringBuilder buffer) {
-		super.construct(buffer);
-		if (value != null) {
-			buffer.append(" \"").append(value).append("\"");
-		}
-		return buffer;
+		return quoteArgumentIfNeeded(super.construct(buffer).append(' ').append(field).append(' '), value);
 	}
+
 	@Override
 	public String getCommand() {
 		return "set";
 	}
+
+
+	@Override
+	public CharSequence parseRest(CharSequence rest) {
+		final Pair<CharSequence, CharSequence> fp = takeString(super.parseRest(rest));
+		field = fp.first.toString();
+		final Pair<CharSequence, CharSequence> vp = takeString(fp.second);
+		value = vp.first.toString();
+
+		return vp.second;
+	}
+
+	/**
+	 * @return the field
+	 */
+	public String getField() {
+		return field;
+	}
+
+	/**
+	 * @return the value
+	 */
+	public String getValue() {
+		return value;
+	}
 }
Index: /java/main/src/main/java/com/framsticks/communication/queries/UseRequest.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/queries/UseRequest.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/queries/UseRequest.java	(revision 96)
@@ -1,3 +1,5 @@
 package com.framsticks.communication.queries;
+
+import com.framsticks.util.lang.Strings;
 
 /**
@@ -19,10 +21,12 @@
 	@Override
 	protected StringBuilder construct(StringBuilder buffer) {
-		return buffer.append(' ').append(feature);
+		return buffer.append(feature);
 	}
 
 	@Override
-	public void parseRest(String rest) {
-		feature = rest;
+	public CharSequence parseRest(CharSequence rest) {
+		feature = rest.toString();
+		Strings.assureNotEmpty(feature);
+		return null;
 	}
 
Index: /java/main/src/main/java/com/framsticks/communication/queries/VersionRequest.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/queries/VersionRequest.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/queries/VersionRequest.java	(revision 96)
@@ -23,11 +23,12 @@
 
 	@Override
-	public void parseRest(String rest) {
-		version = Numbers.parse(rest, Integer.class);
+	public CharSequence parseRest(CharSequence rest) {
+		version = Numbers.parse(rest.toString(), Integer.class);
+		return null;
 	}
 
 	@Override
 	protected StringBuilder construct(StringBuilder buffer) {
-		return buffer.append(' ').append(version);
+		return buffer.append(version);
 	}
 
Index: /java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java
===================================================================
--- /java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java	(revision 96)
@@ -2,4 +2,6 @@
 
 import com.framsticks.communication.StateCallback;
+import com.framsticks.util.FramsticksException;
+
 import org.apache.log4j.Logger;
 
@@ -18,9 +20,10 @@
 
 	@Override
-	public void call(Exception e) {
-		if (e != null) {
-			logger.error("failed to " + message + " with " + e);
-			return;
-		}
+	public void handle(FramsticksException e) {
+		logger.error("failed to " + message + " with " + e);
+	}
+
+	@Override
+	public void callImpl() {
 		logger.debug(message);
 	}
Index: /java/main/src/main/java/com/framsticks/core/AbstractInstance.java
===================================================================
--- /java/main/src/main/java/com/framsticks/core/AbstractInstance.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/core/AbstractInstance.java	(revision 96)
@@ -0,0 +1,162 @@
+package com.framsticks.core;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.params.AccessInterface;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
+import com.framsticks.params.Param;
+import com.framsticks.params.ParamsPackage;
+import com.framsticks.params.Registry;
+import com.framsticks.params.annotations.AutoAppendAnnotation;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.Thread;
+// import static com.framsticks.core.InstanceUtils.*;
+
+/**
+ * @author Piotr Sniegowski
+ */
+@FramsClassAnnotation
+public abstract class AbstractInstance extends Thread<Instance> implements Instance {
+
+	private static final Logger log = Logger.getLogger(Instance.class);
+
+	private Node root;
+
+	@Override
+	public void setRoot(Node node) {
+		root = node;
+	}
+
+	@Override
+	public @Nonnull Node getRoot() {
+		assert root != null;
+		return root;
+	}
+
+	public boolean isRootAssigned() {
+		// assert isActive();
+		return root != null;
+	}
+
+	protected Set<InstanceListener> listeners = new HashSet<InstanceListener>();
+
+	public AbstractInstance() {
+		setName("entity");
+	}
+
+	protected void tryRegisterOnChangeEvents(Path path) {
+
+	}
+
+
+	protected void fireRun(Exception e) {
+		for (InstanceListener l : this.listeners) {
+			l.onRun(e);
+		}
+	}
+
+	protected void fireStop(Exception e) {
+		for (InstanceListener l : this.listeners) {
+			l.onStop(e);
+		}
+	}
+
+	@Override
+	public void addListener(final InstanceListener listener) {
+		assert Dispatching.isThreadSafe();
+		Dispatching.dispatchIfNotActive(this, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				listeners.add(listener);
+			}
+		});
+	}
+
+	@Override
+	public void removeListener(final InstanceListener listener) {
+		assert Dispatching.isThreadSafe();
+		Dispatching.dispatchIfNotActive(this, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				listeners.remove(listener);
+			}
+		});
+	}
+
+	protected void fireListChange(Path path, ListChange change) {
+		assert isActive();
+		for (InstanceListener l : this.listeners) {
+			l.onListChange(path, change);
+		}
+	}
+
+	@Override
+	public void notifyOfFetch(Path path) {
+		fireFetch(path);
+	}
+
+	protected void fireFetch(Path path) {
+		assert isActive();
+		for (InstanceListener l : this.listeners) {
+			l.onFetch(path);
+		}
+	}
+
+
+	@Override
+	public final FramsClass getInfoFromCache(String id) {
+		assert isActive();
+		return registry.getFramsClass(id);
+	}
+
+	protected Registry registry = new Registry();
+
+
+	@Override
+	public @Nonnull AccessInterface prepareAccess(CompositeParam param) {
+		return registry.prepareAccess(param);
+	}
+
+	@Override
+	public void takeAllFrom(Registry source) {
+		registry.takeAllFrom(source);
+	}
+
+	@AutoAppendAnnotation
+	public void usePackage(ParamsPackage paramsPackage) {
+		log.debug("using package " + paramsPackage + " in instance " + this);
+		paramsPackage.register(registry);
+	}
+
+	@AutoAppendAnnotation
+	public void takeFromRegistry(Registry registry) {
+		log.debug("taking from registry " + registry + " in instance " + this);
+		this.registry.takeAllFrom(registry);
+	}
+
+	@Override
+	protected void joinableStart() {
+		dispatch(new RunAt<Instance>() {
+			@Override
+			public void run() {
+				if (!isRootAssigned()) {
+					setRoot(new Node(Param.build().name("Instance").id(getName()).type("o").finish(CompositeParam.class), null));
+				}
+			}
+		});
+		super.joinableStart();
+	}
+
+	@Override
+	public void putInfoIntoCache(FramsClass framclass) {
+		registry.putFramsClass(framclass);
+	}
+}
+
Index: va/main/src/main/java/com/framsticks/core/Entity.java
===================================================================
--- /java/main/src/main/java/com/framsticks/core/Entity.java	(revision 95)
+++ 	(revision )
@@ -1,43 +1,0 @@
-package com.framsticks.core;
-
-
-import com.framsticks.params.annotations.FramsClassAnnotation;
-import com.framsticks.util.dispatching.Joinable;
-
-/**
- * @author Piotr Sniegowski
- */
-@FramsClassAnnotation
-public interface Entity extends Joinable {
-
-	public String getName();
-
-	// /**
-	//  * @param name the name to set
-	//  */
-	// @ParamAnnotation
-	// public final void setName(String name) {
-	// 	this.name = name;
-	// 	if (dispatcher instanceof Thread) {
-	// 		((Thread<Entity>) dispatcher).setName(name);
-	// 	}
-	// }
-
-
-	// public Dispatcher<Entity> createDefaultDispatcher() {
-	// 	return new Thread<Entity>().setName(name).start();
-	// }
-
-	// public void start() {
-	// 	if (dispatcher == null) {
-	// 		log.debug("no dispatcher set for " + this + ", creating default one");
-	// 		dispatcher = createDefaultDispatcher();
-	// 	}
-	// 	invokeLater(new RunAt<Entity>() {
-	// 		@Override
-	// 		public void run() {
-	// 			Entity.this.run();
-	// 		}
-	// 	});
-	// }
-}
Index: /java/main/src/main/java/com/framsticks/core/Framsticks.java
===================================================================
--- /java/main/src/main/java/com/framsticks/core/Framsticks.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/core/Framsticks.java	(revision 96)
@@ -3,4 +3,5 @@
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.parsers.XmlLoader;
+import com.framsticks.util.dispatching.Joinable;
 import com.framsticks.util.dispatching.JoinableCollection;
 import com.framsticks.util.dispatching.Monitor;
@@ -15,5 +16,5 @@
  */
 @FramsClassAnnotation
-public class Framsticks extends JoinableCollection<Entity> {
+public class Framsticks extends JoinableCollection<Joinable> {
 	private static final Logger log = Logger.getLogger(Framsticks.class);
 
@@ -28,11 +29,7 @@
 	public static void main(final String[] args) {
 
-		new Monitor(loadConfiguration(Framsticks.class.getResourceAsStream("/configs/framsticks.xml")))
-			.use()
-			.waitFor()
-			.drop()
-			.join();
+		new Monitor(loadConfiguration(Framsticks.class.getResourceAsStream("/configs/framsticks.xml"))).use().waitFor().drop().join();
 
-		log.info("exiting main");
+		log.debug("exiting main");
 	}
 
Index: /java/main/src/main/java/com/framsticks/core/Instance.java
===================================================================
--- /java/main/src/main/java/com/framsticks/core/Instance.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/core/Instance.java	(revision 96)
@@ -1,420 +1,55 @@
 package com.framsticks.core;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
 
 import javax.annotation.Nonnull;
 
-import org.apache.log4j.Logger;
-
-import com.framsticks.communication.File;
 import com.framsticks.params.AccessInterface;
 import com.framsticks.params.CompositeParam;
-import com.framsticks.params.ConstructionException;
 import com.framsticks.params.FramsClass;
-import com.framsticks.params.ListAccess;
-import com.framsticks.params.Param;
-import com.framsticks.params.ParamsPackage;
 import com.framsticks.params.Registry;
 import com.framsticks.params.ValueParam;
-import com.framsticks.params.annotations.AutoAppendAnnotation;
-import com.framsticks.params.annotations.FramsClassAnnotation;
-import com.framsticks.params.types.ObjectParam;
 import com.framsticks.params.types.ProcedureParam;
-import com.framsticks.parsers.Loaders;
-import com.framsticks.parsers.MultiParamLoader;
-import com.framsticks.util.FramsticksException;
 import com.framsticks.util.StateFunctor;
-import com.framsticks.util.UnsupportedOperationException;
-import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.dispatching.Future;
-import com.framsticks.util.dispatching.RunAt;
-import com.framsticks.util.dispatching.Thread;
-import com.framsticks.util.lang.Casting;
+import com.framsticks.util.dispatching.Joinable;
 
-/**
- * @author Piotr Sniegowski
- */
-@FramsClassAnnotation
-public abstract class Instance extends Thread<Instance> implements Entity {
+public interface Instance extends Dispatcher<Instance>, Joinable {
 
-	private static final Logger log = Logger.getLogger(Instance.class.getName());
+	public @Nonnull Node getRoot();
+	public @Nonnull void setRoot(Node node);
 
-	private Node root;
+	public @Nonnull AccessInterface prepareAccess(CompositeParam param);
+	public void takeAllFrom(Registry source);
 
-	protected @Nonnull Node setRoot(CompositeParam param, Object object) {
-		// if (isRootAssigned()) {
-		// 	throw new FramsticksException().msg("root is already assigned");
-		// }
-		// assert isActive();
-		root = new Node(param, object);
-		return root;
-	}
+	public void addListener(InstanceListener listener);
+	public void removeListener(InstanceListener listener);
 
-	protected @Nonnull Node getRoot() {
-		// assert isActive();
-		assert root != null;
-		return root;
-	}
+	public void notifyOfFetch(Path path);
 
-	public boolean isRootAssigned() {
-		// assert isActive();
-		return root != null;
-	}
+	public FramsClass getInfoFromCache(String id);
 
-	protected Set<InstanceListener> listeners = new HashSet<InstanceListener>();
+	public void putInfoIntoCache(FramsClass framclass);
 
-	public Instance() {
-		setName("entity");
-	}
-
-	protected void fetchInfo(Path path, Future<FramsClass> future) {
-		future.result(null, new UnsupportedOperationException());
-	}
-
-	public void resolve(Path path, Future<Path> future) {
-		assert isActive();
-		assert path.isOwner(this);
-		if (path.getTop().getObject() != null) {
-			future.result(path, null);
-			return;
-		}
-		AccessInterface access = bindAccess(path.getUnder());
-		Object object = access.get(path.getTop().getParam(), Object.class);
-		if (object == null) {
-			future.result(path, null);
-			return;
-		}
-		future.result(path.appendResolution(object), null);
-	}
+	public void resolve(Path path, Future<Path> future);
 
 	/** This is part of the Instance interface.
 	 *
 	 */
-	public abstract void fetchValue(Path path, Param param, StateFunctor stateFunctor);
+	public void fetchValue(Path path, ValueParam param, StateFunctor stateFunctor);
 
 	/** This is part of the Instance interface.
 	 *
 	 */
-	public abstract void fetchValues(Path path, StateFunctor stateFunctor);
+	public void fetchValues(Path path, StateFunctor stateFunctor);
 
 	/** This is part of the Instance interface.
 	 *
 	 */
-	public abstract void call(Path path, ProcedureParam param, Object[] arguments, StateFunctor stateFunctor);
+	public void call(Path path, ProcedureParam param, Object[] arguments, Future<Object> future);
 
-	protected void tryRegisterOnChangeEvents(Path path) {
+	public void storeValue(Path path, ValueParam param, Object value, StateFunctor stateFunctor);
 
-	}
+	public void fetchInfo(Path path, Future<FramsClass> future);
 
-	public void storeValue(Path path, Param param, Object value, final StateFunctor stateFunctor) {
-		assert isActive();
-		dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				stateFunctor.call(new UnsupportedOperationException());
-			}
-		});
-	}
-
-	protected void fireRun(Exception e) {
-		for (InstanceListener l : this.listeners) {
-			l.onRun(e);
-		}
-	}
-
-	protected void fireStop(Exception e) {
-		for (InstanceListener l : this.listeners) {
-			l.onStop(e);
-		}
-	}
-
-	public void addListener(final InstanceListener listener) {
-		assert Dispatching.isThreadSafe();
-		Dispatching.dispatchIfNotActive(this, new RunAt<Instance>() {
-			@Override
-			public void run() {
-				listeners.add(listener);
-			}
-		});
-	}
-
-	public void removeListener(final InstanceListener listener) {
-		assert Dispatching.isThreadSafe();
-		Dispatching.dispatchIfNotActive(this, new RunAt<Instance>() {
-			@Override
-			public void run() {
-				listeners.remove(listener);
-			}
-		});
-	}
-
-	protected void fireListChange(Path path, ListChange change) {
-		assert isActive();
-		for (InstanceListener l : this.listeners) {
-			l.onListChange(path, change);
-		}
-	}
-
-	protected void fireFetch(Path path) {
-		assert isActive();
-		for (InstanceListener l : this.listeners) {
-			l.onFetch(path);
-		}
-	}
-
-	public final FramsClass getInfoFromCache(Path path) {
-		return getInfoFromCache(path.getTop().getParam().getContainedTypeName());
-	}
-
-	public FramsClass getInfoFromCache(String id) {
-		assert isActive();
-		return registry.getFramsClass(id);
-	}
-
-	protected Registry registry = new Registry();
-
-	public AccessInterface createAccess(String name) throws ConstructionException {
-		assert isActive();
-		return registry.createAccess(name);
-	}
-
-	// TODO: make ValueParam
-	public <T> T get(Node node, Param childParam, Class<T> type) {
-		return bindAccess(node).get((ValueParam) childParam, type);
-	}
-
-	public void findInfo(final Path path, final Future<FramsClass> future) {
-		assert isActive();
-		final String name = path.getTop().getParam().getContainedTypeName();
-		final FramsClass framsClass = getInfoFromCache(name);
-		if (framsClass != null) {
-			log.trace("info for " + name + " found in cache");
-			future.result(framsClass, null);
-			return;
-		}
-		fetchInfo(path, future);
-	}
-
-	public final AccessInterface bindAccess(String path) {
-		return bindAccess(getPath(path));
-	}
-
-	public final AccessInterface bindAccess(Node node) {
-		assert isActive();
-		assert node.getObject() != null;
-
-		try {
-			AccessInterface access = registry.prepareAccess(node.getParam());
-			if (access == null) {
-				throw new FramsticksException().msg("failed to prepare access for param").arg("param", node.getParam());
-			}
-			return access.select(node.getObject());
-		} catch (ConstructionException e) {
-			log.error("failed to bind access for " + node.getParam() + ": " + e);
-		}
-		return null;
-	}
-
-	public final <T> T getParam(Path path, String id, Class<T> type) {
-		return Casting.tryCast(type, registry.prepareAccess(path.getTop().getParam()).getParam(id));
-	}
-
-	public final AccessInterface bindAccess(Path path) {
-		path.assureResolved();
-		return bindAccess(path.getTop());
-	}
-
-	public void resolve(final String targetPath, final Future<Path> future) {
-		assert isActive();
-		final Path path = getPath(targetPath);
-		resolve(path, new Future<Path>() {
-			@Override
-			public void result(Path result, Exception e) {
-				assert isActive();
-				if (e != null) {
-					future.result(path, e);
-					return;
-				}
-				if (path.isResolved(targetPath)) {
-					future.result(path, null);
-					return;
-				}
-				if (path.isResolved()) {
-					future.result(path, new Exception("testing"));
-					return;
-				}
-				resolve(targetPath, future);
-			}
-		});
-	}
-
-	public void resolveAndFetch(final String targetPath, final Future<Path> future) {
-		assert isActive();
-		resolve(targetPath, new Future<Path>() {
-			@Override
-			public void result(final Path path, Exception e) {
-				if (e != null) {
-					future.result(path, e);
-					return;
-				}
-				assert path.isResolved(targetPath);
-				fetchValues(path, new StateFunctor() {
-					@Override
-					public void call(Exception e) {
-						future.result(path, e);
-					}
-				});
-			}
-		});
-	}
-
-	public Path createIfNeeded(String path) {
-		Path p;
-		while (!(p = getPath(path)).isResolved(path)) {
-			create(p);
-		}
-		return p;
-	}
-
-	public Path createIfNeeded(Path path) {
-		assert isActive();
-		if (path.isResolved()) {
-			return path;
-		}
-		return create(path);
-	}
-
-	public Path create(Path path) {
-		assert isActive();
-		assert !path.isResolved();
-		Path resolved = path.tryFindResolution();
-		if (!resolved.isResolved()) {
-			log.debug("creating: " + path);
-			AccessInterface access = registry.prepareAccess(path.getTop().getParam());
-			assert access != null;
-			Object child = access.createAccessee();
-			assert child != null;
-			if (path.size() == 1) {
-				setRoot(getRoot().getParam(), child);
-			} else {
-				bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
-			}
-			resolved = path.appendResolution(child);
-		}
-		tryRegisterOnChangeEvents(resolved);
-		return resolved;
-	}
-
-
-
-
-	public @Nonnull FramsClass processFetchedInfo(File file) {
-		assert isActive();
-		FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
-		if ("/".equals(file.getPath())) {
-			if (getRoot().getParam().getContainedTypeName() == null) {
-				setRoot(Param.build().name("Instance").id(getName()).type("o " + framsClass.getId()).finish(CompositeParam.class), getRoot().getObject());
-			}
-		}
-		registry.putFramsClass(framsClass);
-		return framsClass;
-	}
-
-	public void processFetchedValues(Path path, List<File> files) {
-		assert isActive();
-		assert files.size() == 1;
-		assert path.isTheSame(files.get(0).getPath());
-		Node node = path.getTop();
-		MultiParamLoader loader = new MultiParamLoader();
-		loader.setNewSource(files.get(0).getContent());
-		loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
-
-		try {
-			if (node.getParam() instanceof ObjectParam) {
-				loader.addAccessInterface(bindAccess(node));
-				loader.go();
-				fireFetch(path);
-				return;
-			}
-
-			ListAccess listAccess = ((ListAccess)bindAccess(node));
-			assert listAccess != null;
-			listAccess.clearValues();
-
-			AccessInterface elementAccess = listAccess.getElementAccess();
-			loader.addAccessInterface(elementAccess);
-			MultiParamLoader.Status status;
-			while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
-				if (status == MultiParamLoader.Status.AfterObject) {
-					AccessInterface accessInterface = loader.getLastAccessInterface();
-
-					String id = listAccess.computeIdentifierFor(accessInterface.getSelected());
-					//TODO listAccessParam
-					Param param = Param.build().forAccess(accessInterface).id(id).finish();
-					Object child = accessInterface.getSelected();
-					accessInterface.select(null);
-					assert child != null;
-					bindAccess(node).set((ValueParam) param, child);
-				}
-			}
-
-			fireFetch(path);
-		} catch (Exception e) {
-			log.error("exception occurred while loading: " + e);
-		}
-
-	}
-
-	public static Iterator<String> splitPath(String path) {
-		List<String> list = new LinkedList<String>();
-		for (String s : path.split("/")) {
-			if (!s.isEmpty()) {
-				list.add(s);
-			}
-		}
-		return list.iterator();
-	}
-
-	public Registry getRegistry() {
-		return registry;
-	}
-
-	public Path getPath(String textual) {
-		return Path.build().resolve(this, textual).finish();
-	}
-
-	public Path getRootPath() {
-		return getPath("/");
-	}
-
-	@AutoAppendAnnotation
-	public void usePackage(ParamsPackage paramsPackage) {
-		log.debug("using package " + paramsPackage + " in instance " + this);
-		paramsPackage.register(registry);
-	}
-
-	@AutoAppendAnnotation
-	public void takeFromRegistry(Registry registry) {
-		log.debug("taking from registry " + registry + " in instance " + this);
-		this.registry.takeAllFrom(registry);
-	}
-
-	@Override
-	protected void joinableStart() {
-		dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				if (!isRootAssigned()) {
-					setRoot(Param.build().name("Instance").id(getName()).type("o").finish(CompositeParam.class), null);
-				}
-			}
-		});
-		super.joinableStart();
-	}
-
+	public Path create(Path path);
 }
-
Index: /java/main/src/main/java/com/framsticks/core/InstanceUtils.java
===================================================================
--- /java/main/src/main/java/com/framsticks/core/InstanceUtils.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/core/InstanceUtils.java	(revision 96)
@@ -0,0 +1,242 @@
+package com.framsticks.core;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.communication.File;
+import com.framsticks.params.AccessInterface;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
+import com.framsticks.params.ListAccess;
+import com.framsticks.params.Param;
+import com.framsticks.params.ValueParam;
+import com.framsticks.params.types.ObjectParam;
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.parsers.Loaders;
+import com.framsticks.parsers.MultiParamLoader;
+import com.framsticks.util.AbstractStateFunctor;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.StateFunctor;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.RunAt;
+
+import static com.framsticks.util.dispatching.Dispatching.*;
+
+public final class InstanceUtils {
+
+	private static final Logger log = Logger.getLogger(InstanceUtils.class.getName());
+
+	private InstanceUtils() {
+	}
+
+	public static @Nonnull FramsClass processFetchedInfo(Instance instance, File file) {
+		assert instance.isActive();
+		FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
+		if ("/".equals(file.getPath())) {
+			if (instance.getRoot().getParam().getContainedTypeName() == null) {
+				instance.setRoot(new Node(Param.build().name("Instance").id(instance.getName()).type("o " + framsClass.getId()).finish(CompositeParam.class), instance.getRoot().getObject()));
+			}
+		}
+		instance.putInfoIntoCache(framsClass);
+		return framsClass;
+	}
+
+	public static void findInfo(final Path path, final Future<FramsClass> future) {
+		Instance instance = path.getInstance();
+		assert instance.isActive();
+		final String name = path.getTop().getParam().getContainedTypeName();
+		final FramsClass framsClass = instance.getInfoFromCache(name);
+		if (framsClass != null) {
+			log.trace("info for " + name + " found in cache");
+			future.pass(framsClass);
+			return;
+		}
+		instance.fetchInfo(path, future);
+	}
+
+	public static void processFetchedValues(Path path, List<File> files) {
+		Instance instance = path.getInstance();
+		assert instance.isActive();
+		assert files.size() == 1;
+		assert path.isTheSame(files.get(0).getPath());
+		Node node = path.getTop();
+		MultiParamLoader loader = new MultiParamLoader();
+		loader.setNewSource(files.get(0).getContent());
+		loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
+
+		try {
+			if (node.getParam() instanceof ObjectParam) {
+				loader.addAccessInterface(InstanceUtils.bindAccess(instance, node));
+				loader.go();
+				instance.notifyOfFetch(path);
+				return;
+			}
+
+			ListAccess listAccess = ((ListAccess) InstanceUtils.bindAccess(instance, node));
+			assert listAccess != null;
+			listAccess.clearValues();
+
+			AccessInterface elementAccess = listAccess.getElementAccess();
+			loader.addAccessInterface(elementAccess);
+			MultiParamLoader.Status status;
+			while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
+				if (status == MultiParamLoader.Status.AfterObject) {
+					AccessInterface accessInterface = loader.getLastAccessInterface();
+
+					String id = listAccess.computeIdentifierFor(accessInterface.getSelected());
+					//TODO listAccessParam
+					Param param = Param.build().forAccess(accessInterface).id(id).finish();
+					Object child = accessInterface.getSelected();
+					accessInterface.select(null);
+					assert child != null;
+					InstanceUtils.bindAccess(instance, node).set((ValueParam) param, child);
+				}
+			}
+
+			instance.notifyOfFetch(path);
+		} catch (Exception e) {
+			log.error("exception occurred while loading: " + e);
+		}
+
+	}
+
+	public static void resolveAndFetch(final Instance instance, final String targetPath, final Future<Path> future) {
+		assert instance.isActive();
+		InstanceUtils.resolve(instance, targetPath, new Future<Path>(future) {
+			@Override
+			protected void result(final Path path) {
+				assert path.isResolved(targetPath);
+				//TODO Future
+				instance.fetchValues(path, new AbstractStateFunctor(future) {
+					@Override
+					public void call() {
+						future.pass(path);
+					}
+				});
+			}
+		});
+	}
+
+
+	public static void resolve(final Path path, final Future<Path> future) {
+		final Instance instance = path.getInstance();
+		assert instance.isActive();
+		if (path.getTop().getObject() != null) {
+			if (getInfoFromCache(path) != null) {
+				future.pass(path);
+				return;
+			}
+			InstanceUtils.findInfo(path, new Future<FramsClass>(future) {
+				@Override
+				protected void result(FramsClass result) {
+					future.pass(path);
+				}
+			});
+			return;
+		}
+		InstanceUtils.findInfo(path, new Future<FramsClass>(future) {
+			@Override
+			protected void result(FramsClass result) {
+				assert instance.isActive();
+				assert path.getTop().getParam().isMatchingContainedName(result.getId());
+				Path p = (path.getTop().getParam().getContainedTypeName() != null ? path : path.tryFindResolution());
+				future.pass(InstanceUtils.createIfNeeded(p));
+			}
+		});
+	}
+
+	public static Path createIfNeeded(Instance instance, String path) {
+		assert instance.isActive();
+		Path p;
+		while (!(p = Path.to(instance, path)).isResolved(path)) {
+			instance.create(p);
+		}
+		return p;
+	}
+
+	public static Path createIfNeeded(Path path) {
+		Instance instance = path.getInstance();
+		assert instance.isActive();
+		if (path.isResolved()) {
+			return path;
+		}
+		return instance.create(path);
+	}
+
+	public static @Nonnull AccessInterface bindAccess(Instance instance, String path) {
+		return bindAccess(Path.to(instance, path));
+	}
+
+	public static @Nonnull AccessInterface bindAccess(Instance instance, Node node) {
+		assert instance.isActive();
+		assert node.getObject() != null;
+
+		try {
+			AccessInterface access = instance.prepareAccess(node.getParam());
+			if (access == null) {
+				throw new FramsticksException().msg("failed to prepare access for param").arg("param", node.getParam());
+			}
+			return access.select(node.getObject());
+		} catch (FramsticksException e) {
+			throw new FramsticksException().msg("failed to prepare access for param").arg("param", node.getParam()).cause(e);
+			// log.error("failed to bind access for " + node.getParam() + ": " + e);
+		}
+	}
+
+	public static @Nonnull AccessInterface bindAccess(Path path) {
+		assert path.getInstance().isActive();
+		path.assureResolved();
+		return bindAccess(path.getInstance(), path.getTop());
+	}
+
+	public static void storeValue(final Path path, final ValueParam param, final Object value, final StateFunctor stateFunctor) {
+		final Instance instance = path.getInstance();
+
+		dispatchIfNotActive(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				instance.storeValue(path, param, value, stateFunctor);
+			}
+		});
+	}
+
+	public static void call(final Path path, final ProcedureParam param, final Object[] arguments, final Future<Object> future) {
+		final Instance instance = path.getInstance();
+
+		dispatchIfNotActive(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				instance.call(path, param, arguments, future);
+			}
+		});
+	}
+
+	/** This might not be correct. */
+	public static void resolve(final Instance instance, final String targetPath, final Future<Path> future) {
+		dispatchIfNotActive(instance, new RunAt<Instance>() {
+
+			@Override
+			public void run() {
+				instance.resolve(Path.to(instance, targetPath), new Future<Path>(future) {
+					@Override
+					protected void result(Path result) {
+						assert result.getInstance().isActive();
+						if (result.isResolved(targetPath)) {
+							future.pass(result);
+							return;
+						}
+						resolve(result.getInstance(), targetPath, future);
+					}
+				});
+			}
+		});
+	}
+
+	public static FramsClass getInfoFromCache(Path path) {
+		assert path.getInstance().isActive();
+		return path.getInstance().getInfoFromCache(path.getTop().getParam().getContainedTypeName());
+	}
+}
Index: va/main/src/main/java/com/framsticks/core/LocalInstance.java
===================================================================
--- /java/main/src/main/java/com/framsticks/core/LocalInstance.java	(revision 95)
+++ 	(revision )
@@ -1,95 +1,0 @@
-package com.framsticks.core;
-
-import com.framsticks.hosting.InstanceClient;
-import com.framsticks.util.dispatching.Thread;
-
-import org.apache.log4j.Logger;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.util.HashSet;
-import java.util.Set;
-import com.framsticks.util.dispatching.RunAt;
-
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class LocalInstance extends Instance {
-
-	private static final Logger log = Logger.getLogger(LocalInstance.class.getName());
-
-	public LocalInstance() {
-
-	}
-
-	// @Override
-	// public void configure(Configuration config) {
-	// 	Integer accept = config.getInteger("accept", null);
-	// 	if (accept != null) {
-	// 		try {
-	// 			acceptSocket = new ServerSocket();
-	// 			acceptSocket.setReuseAddress(true);
-	// 			acceptThread = new Thread<Accept>().setName(name + "-accept").start();
-	// 			tryBind(accept);
-	// 		} catch (IOException e) {
-	// 			log.fatal("failed to create accept socket: " + e);
-	// 		}
-	// 	}
-	// }
-
-	protected final Set<InstanceClient> clients = new HashSet<InstanceClient>();
-	ServerSocket acceptSocket;
-
-	public static class Accept {
-	};
-
-	Thread<Accept> acceptThread;
-
-	protected void acceptNext() {
-		acceptThread.dispatch(new RunAt<Accept>() {
-			@Override
-			public void run() {
-				try {
-					final Socket socket = acceptSocket.accept();
-					assert socket != null;
-					log.debug("accepted socket: " + socket.getInetAddress().getHostAddress());
-					dispatch(new RunAt<LocalInstance>() {
-						@Override
-						public void run() {
-							InstanceClient client = new InstanceClient(LocalInstance.this, socket);
-							clients.add(client);
-							log.info("client connected: " + client);
-						}
-					});
-				} catch (IOException e) {
-					log.error("failed to accept socket: " + e);
-				}
-				acceptNext();
-			}
-		});
-	}
-
-	public void tryBind(final Integer accept) {
-		acceptThread.dispatch(new RunAt<Accept>() {
-			@Override
-			public void run() {
-				try {
-					acceptSocket.bind(new InetSocketAddress(accept));
-					log.debug("started accepting on port " + accept);
-					acceptNext();
-				} catch (IOException e) {
-					log.fatal("failed to accept on port " + accept + ": " + e);
-				}
-				try {
-					java.lang.Thread.sleep(1000);
-				} catch (InterruptedException ignored) {
-				}
-				tryBind(accept);
-			}
-		});
-	}
-
-}
Index: /java/main/src/main/java/com/framsticks/core/ObjectInstance.java
===================================================================
--- /java/main/src/main/java/com/framsticks/core/ObjectInstance.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/core/ObjectInstance.java	(revision 96)
@@ -5,13 +5,18 @@
 import com.framsticks.params.AccessInterface;
 import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
 import com.framsticks.params.Param;
+import com.framsticks.params.ValueParam;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.UnsupportedOperationException;
 import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.util.FramsticksException;
 import com.framsticks.util.StateFunctor;
+import com.framsticks.util.dispatching.Future;
+// import static com.framsticks.core.InstanceUtils.*;
 
 @FramsClassAnnotation
-public class ObjectInstance extends Instance {
+public class ObjectInstance extends AbstractInstance {
 	private static final Logger log = Logger.getLogger(ObjectInstance.class);
 
@@ -20,5 +25,5 @@
 		registry.registerAndBuild(object.getClass());
 		AccessInterface access = registry.createAccess(object.getClass());
-		setRoot(Param.build().forAccess(access).id(getName()).finish(CompositeParam.class), object);
+		setRoot(new Node(Param.build().forAccess(access).id(getName()).finish(CompositeParam.class), object));
 	}
 
@@ -43,23 +48,66 @@
 		log.debug("requesting: " + path);
 		fireFetch(path);
-		stateFunctor.call(null);
+		stateFunctor.call();
 	}
 
 	@Override
-	public void fetchValue(Path path, Param param, StateFunctor stateFunctor) {
+	public void fetchValue(Path path, ValueParam param, StateFunctor stateFunctor) {
 		assert isActive();
 		fireFetch(path);
-		stateFunctor.call(null);
+		stateFunctor.call();
 	}
 
 	@Override
-	public void call(Path path, ProcedureParam param, Object[] arguments, StateFunctor stateFunctor) {
+	public void call(Path path, ProcedureParam param, Object[] arguments, Future<Object> future) {
 		assert isActive();
 		try {
-			bindAccess(path).call(param, arguments);
-			stateFunctor.call(null);
+			future.pass(InstanceUtils.bindAccess(path).call(param, arguments));
 		} catch (FramsticksException e) {
-			stateFunctor.call(e);
+			future.handle(e);
 		}
 	}
+
+	@Override
+	public void fetchInfo(Path path, Future<FramsClass> future) {
+		assert isActive();
+		Path p = path.tryResolveIfNeeded();
+		Class<?> javaClass = p.getTopObject().getClass();
+		FramsClass framsClass = registry.registerReflectedIfNeeded(javaClass);
+		if (framsClass != null) {
+			future.pass(framsClass);
+		} else {
+			future.handle(new FramsticksException().msg("failed to find info for class").arg("java class", javaClass));
+		}
+	}
+
+	@Override
+	public void resolve(Path path, Future<Path> future) {
+		assert isActive();
+		assert path.isOwner(this);
+		if (path.getTop().getObject() != null) {
+			future.pass(path);
+			return;
+		}
+		AccessInterface access = InstanceUtils.bindAccess(this, path.getUnder());
+		Object object = access.get(path.getTop().getParam(), Object.class);
+		if (object == null) {
+			future.pass(path);
+			return;
+		}
+		future.pass(path.appendResolution(object));
+	}
+
+	@Override
+	public void storeValue(Path path, ValueParam param, Object value, final StateFunctor stateFunctor) {
+		assert isActive();
+		stateFunctor.handle(new UnsupportedOperationException());
+	}
+
+	@Override
+	public Path create(Path path) {
+		assert isActive();
+		assert !path.isResolved();
+		throw new UnsupportedOperationException();
+	}
+
 }
Index: /java/main/src/main/java/com/framsticks/core/Path.java
===================================================================
--- /java/main/src/main/java/com/framsticks/core/Path.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/core/Path.java	(revision 96)
@@ -11,4 +11,5 @@
 import java.util.List;
 
+import javax.annotation.Nonnull;
 import javax.annotation.concurrent.Immutable;
 
@@ -32,5 +33,5 @@
 		}
 		try {
-			instance.registry.prepareAccess(param);
+			instance.prepareAccess(param);
 			return child;
 		} catch (FramsticksException e) {
@@ -119,5 +120,15 @@
 		}
 
-		public PathBuilder resolve(Instance instance, String textual) {
+		public static Iterator<String> splitPath(String path) {
+			List<String> list = new LinkedList<String>();
+			for (String s : path.split("/")) {
+				if (!s.isEmpty()) {
+					list.add(s);
+				}
+			}
+			return list.iterator();
+		}
+
+		public PathBuilder resolve(@Nonnull Instance instance, String textual) {
 
 			assert nodes.isEmpty();
@@ -129,7 +140,7 @@
 
 			StringBuilder b = new StringBuilder();
-			Iterator<String> i = Instance.splitPath(textual);
+			Iterator<String> i = splitPath(textual);
 			while (i.hasNext() && current.getObject() != null) {
-				AccessInterface access = instance.registry.prepareAccess(current.getParam());
+				AccessInterface access = instance.prepareAccess(current.getParam());
 				if (access == null) {
 					break;
@@ -205,9 +216,15 @@
 	}
 
-	public final Instance getInstance() {
+	public final @Nonnull Instance getInstance() {
 		assert Dispatching.isThreadSafe();
 		return instance;
 	}
 
+	public Path tryResolveIfNeeded() {
+		if (isResolved()) {
+			return this;
+		}
+		return tryFindResolution();
+	}
 
 	/** Attach resolution at end, if available.
@@ -221,5 +238,5 @@
 			return Path.build().resolve(instance, "/").finish();//appendResolution(instance.root.object);
 		}
-		Object child = getKnownChild(instance, instance.bindAccess(getUnder()), getTop().getParam());
+		Object child = getKnownChild(instance, InstanceUtils.bindAccess(instance, getUnder()), getTop().getParam());
 		if (child == null) {
 			return this;
@@ -266,4 +283,8 @@
 		}
 	}
+
+	public static Path to(@Nonnull Instance instance, String textual) {
+		return Path.build().resolve(instance, textual).finish();
+	}
 }
 
Index: /java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java
===================================================================
--- /java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java	(revision 96)
@@ -1,4 +1,3 @@
 package com.framsticks.diagnostics;
-
 
 import java.util.Date;
@@ -14,8 +13,10 @@
 import com.framsticks.core.AbstractInstanceListener;
 import com.framsticks.core.Instance;
+import com.framsticks.core.Path;
 import com.framsticks.dumping.PrintWriterSink;
 import com.framsticks.dumping.SaveStream;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.remote.RecursiveFetcher;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.Logging;
 import com.framsticks.util.PeriodicTask;
@@ -28,6 +29,5 @@
  */
 public class Diagnostics extends JoinableCollection<Instance> {
-	private static final Logger log =
-		Logger.getLogger(Diagnostics.class);
+	private static final Logger log = Logger.getLogger(Diagnostics.class);
 
 
@@ -59,19 +59,26 @@
 
 							log.info("starting periodic dump");
-							new RecursiveFetcher(instance, instance.getRootPath(), new StateFunctor() {
+							new RecursiveFetcher(instance, Path.to(instance, "/"), new StateFunctor() {
 								@Override
-								public void call(Exception e) {
-									if (Logging.log(log, "recursively fetch", instance, e)) {
-										again();
-										return;
-									}
+								public void handle(FramsticksException e) {
+									Logging.log(log, "recursively fetch", instance, e);
+									again();
+								}
+
+								@Override
+								public void call() {
 									log.info("instance resolved, saving");
 									try {
 										final String fileName = dumpsPath + "/" + instance + "_" + new SimpleDateFormat(dumpsFormat).format(new Date()) + ".param";
 										File file = new File(fileName);
-										new SaveStream(new PrintWriterSink(new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), Encoding.getFramsticksCharset()))), instance, instance.getRootPath(), new StateFunctor() {
+										new SaveStream(new PrintWriterSink(new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), Encoding.getFramsticksCharset()))), instance, Path.to(instance, "/"), new StateFunctor() {
 											@Override
-											public void call(Exception e) {
+											public void handle(FramsticksException e) {
 												Logging.log(log, "periodic dump in " + fileName + " of", instance, e);
+												again();
+											}
+
+											@Override
+											public void call() {
 												again();
 											}
Index: va/main/src/main/java/com/framsticks/dumping/FileInstance.java
===================================================================
--- /java/main/src/main/java/com/framsticks/dumping/FileInstance.java	(revision 95)
+++ 	(revision )
@@ -1,80 +1,0 @@
-package com.framsticks.dumping;
-
-import com.framsticks.core.LocalInstance;
-import com.framsticks.core.Path;
-import com.framsticks.core.Instance;
-import com.framsticks.params.annotations.FramsClassAnnotation;
-import com.framsticks.params.annotations.ParamAnnotation;
-import com.framsticks.util.dispatching.Future;
-import com.framsticks.util.dispatching.RunAt;
-import com.framsticks.util.io.Encoding;
-
-import org.apache.log4j.Logger;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-
-/**
- * @author Piotr Sniegowski
- */
-@FramsClassAnnotation
-public abstract class FileInstance extends LocalInstance {
-
-	private static final Logger log = Logger.getLogger(Instance.class.getName());
-	protected File file;
-
-	public FileInstance() {
-	}
-
-	@ParamAnnotation
-	public void setFilename(String filename) {
-		file = new File(filename);
-	}
-
-	@ParamAnnotation
-	public String getFilename() {
-		return file.getName();
-	}
-
-	@Override
-	public String toString() {
-		return "file@" + file.getName();
-	}
-
-	@Override
-	protected void joinableStart() {
-		dispatch(new RunAt<Instance>() {
-
-			@Override
-			public void run() {
-				assert isActive();
-
-				try {
-					LoadStream stream = new LoadStream(FileInstance.this.getRootPath(), new BufferedReader(new InputStreamReader(new FileInputStream(file), Encoding.getFramsticksCharset())), FileInstance.this, new Future<Path>() {
-						@Override
-						public void result(Path result, Exception e) {
-							if (e != null) {
-								log.error("failed to load file instance " + FileInstance.this + ": " + e);
-								fireRun(e);
-								return;
-							}
-							log.info("loaded file instance " + FileInstance.this);
-							fireRun(null);
-						}
-					});
-					stream.load();
-				} catch (IOException e) {
-					log.error("io failure: " + e);
-					fireRun(e);
-				}
-			}
-
-		});
-		super.joinableStart();
-	}
-
-}
Index: /java/main/src/main/java/com/framsticks/dumping/LoadStream.java
===================================================================
--- /java/main/src/main/java/com/framsticks/dumping/LoadStream.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/dumping/LoadStream.java	(revision 96)
@@ -2,4 +2,5 @@
 
 import com.framsticks.communication.File;
+import com.framsticks.core.InstanceUtils;
 import com.framsticks.core.Path;
 import com.framsticks.params.ListSource;
@@ -19,5 +20,5 @@
  * @author Piotr Sniegowski
  */
-public class LoadStream {
+public class LoadStream extends Stream {
 
 	private final static Logger log = Logger.getLogger(LoadStream.class.getName());
@@ -46,5 +47,5 @@
 			while ((line = stream.readLine()) != null) {
 				if (query == null) {
-					query = Strings.splitIntoPair(line, ' ', "\n");
+					query = Strings.splitIntoPair(line, ' ', "");
 					files = new LinkedList<File>();
 					log.trace("loading " + line);
@@ -58,9 +59,9 @@
 					if (line.equals("ok")) {
 						if (query.first.equals("get")) {
-							Path path = instance.createIfNeeded(query.second);
-							instance.processFetchedValues(path, files);
+							Path path = InstanceUtils.createIfNeeded(instance, query.second);
+							InstanceUtils.processFetchedValues(path, files);
 						} else if (query.first.equals("info")) {
 							assert files.size() == 1;
-							instance.processFetchedInfo(files.get(0));
+							InstanceUtils.processFetchedInfo(instance, files.get(0));
 						} else {
 							assert false;
@@ -82,9 +83,9 @@
 		} catch (IOException e) {
 			log.error("failed to load: " + e);
-			future.result(null, e);
+			future.handle(new FramsticksException().msg("failed to load stream").cause(e));
 			return;
 		}
 		log.info("loaded in: " + stopwatch);
-		future.result(instance.getPath(mountPath.getTextual()), null);
+		future.pass(Path.to(instance, mountPath.getTextual()));
 	}
 
Index: /java/main/src/main/java/com/framsticks/dumping/SaveStream.java
===================================================================
--- /java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 96)
@@ -1,4 +1,5 @@
 package com.framsticks.dumping;
 
+import static com.framsticks.core.InstanceUtils.*;
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
@@ -22,5 +23,5 @@
  * @author Piotr Sniegowski
  */
-public class SaveStream {
+public class SaveStream extends Stream {
 
 	private final static Logger log = Logger.getLogger(SaveStream.class.getName());
@@ -55,5 +56,5 @@
 		assert instance.isActive();
 		log.info("stored in " + stopwatch);
-		stateFunctor.call(null);
+		stateFunctor.call();
 	}
 
@@ -63,5 +64,5 @@
 			log.debug("path " + path + " is not resolved - skipping");
 		} else {
-			AccessInterface access = instance.bindAccess(path);
+			AccessInterface access = bindAccess(path);
 			assert access != null;
 			FramsClass framsClass = access.getFramsClass();
@@ -85,5 +86,5 @@
 			for (CompositeParam p : filterInstanceof(access.getParams(), CompositeParam.class)) {
 				final Path childPath = path.appendNode(new Node(p, access.get(p, Object.class)));
-				if (childPath.isResolved() && instance.getInfoFromCache(childPath) != null) {
+				if (childPath.isResolved() && getInfoFromCache(childPath) != null) {
 					dispatchWrite(childPath);
 				}
Index: /java/main/src/main/java/com/framsticks/dumping/Stream.java
===================================================================
--- /java/main/src/main/java/com/framsticks/dumping/Stream.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/dumping/Stream.java	(revision 96)
@@ -0,0 +1,5 @@
+package com.framsticks.dumping;
+
+public class Stream {
+
+}
Index: /java/main/src/main/java/com/framsticks/gui/Browser.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 96)
@@ -5,5 +5,4 @@
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
-import com.framsticks.util.Logging;
 import com.framsticks.util.dispatching.AbstractJoinable;
 import com.framsticks.util.dispatching.Dispatcher;
@@ -22,5 +21,4 @@
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import com.framsticks.util.dispatching.RunAt;
 
@@ -29,5 +27,5 @@
  */
 @FramsClassAnnotation
-public class Browser extends AbstractJoinable implements Dispatcher<Browser>, Entity, JoinableParent {
+public class Browser extends AbstractJoinable implements Dispatcher<Browser>, JoinableParent {
 
 	private static final Logger log = Logger.getLogger(Browser.class.getName());
@@ -72,19 +70,14 @@
 			@Override
 			public void run() {
-				i.resolveAndFetch(path, new Future<Path>() {
+				InstanceUtils.resolveAndFetch(i, path, new Future<Path>(future) {
 					@Override
-					public void result(final Path p, Exception e) {
-						Logging.log(log, "auto resolve path", path, e);
-						if (future != null) {
-							future.result(p, e);
-						}
-						if (e == null) {
-							mainFrame.dispatch(new RunAt<Frame>() {
-								@Override
-								public void run() {
-									mainFrame.goTo(p);
-								}
-							});
-						}
+					protected void result(final Path p) {
+						future.pass(p);
+						mainFrame.dispatch(new RunAt<Frame>() {
+							@Override
+							public void run() {
+								mainFrame.goTo(p);
+							}
+						});
 					}
 				});
@@ -132,5 +125,5 @@
 				@Override
 				public void run() {
-					final Path p = i.getRootPath();
+					final Path p = Path.to(i, "/");
 					dispatch(new RunAt<Browser>() {
 						@Override
@@ -194,6 +187,6 @@
 	 * @return the instances
 	 */
-	public Map<String, Instance> getInstances() {
-		return instances.getObservables();
+	public JoinableCollection<Instance> getInstances() {
+		return instances;
 	}
 
@@ -254,5 +247,4 @@
 	@Override
 	protected void joinableFinish() {
-		// TODO Auto-generated method stub
 
 	}
Index: /java/main/src/main/java/com/framsticks/gui/Frame.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 96)
@@ -1,5 +1,4 @@
 package com.framsticks.gui;
 
-import com.framsticks.core.Entity;
 import com.framsticks.core.Instance;
 import com.framsticks.core.Path;
@@ -32,5 +31,5 @@
  */
 @SuppressWarnings("serial")
-public class Frame extends JoinableCollection<Instance> implements Entity, Dispatcher<Frame> {
+public class Frame extends JoinableCollection<Instance> implements Dispatcher<Frame> {
 
 	private static final Logger log = Logger.getLogger(Frame.class.getName());
@@ -82,5 +81,5 @@
 			public void windowClosing(WindowEvent e) {
 				log.info("received closing");
-				joinableFinish();
+				interrupt();
 			}
 		});
@@ -268,5 +267,5 @@
 		assert isActive();
 		Instance instance = path.getInstance();
-		assert browser.getInstances().containsValue(instance);
+		assert browser.getInstances().contains(instance);
 
 		InstanceAtFrame e = new InstanceAtFrame(instance, this);
Index: /java/main/src/main/java/com/framsticks/gui/TreeNode.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/TreeNode.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/gui/TreeNode.java	(revision 96)
@@ -5,4 +5,5 @@
 import com.framsticks.communication.util.LoggingStateCallback;
 import com.framsticks.core.Instance;
+import com.framsticks.core.InstanceUtils;
 import com.framsticks.core.ListChange;
 import com.framsticks.core.Path;
@@ -15,8 +16,9 @@
 import com.framsticks.remote.*;
 import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Holder;
 import com.framsticks.util.swing.TooltipConstructor;
 import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.AbstractStateFunctor;
 import com.framsticks.util.Logging;
-import com.framsticks.util.StateFunctor;
 import org.apache.log4j.Logger;
 import com.framsticks.util.dispatching.RunAt;
@@ -29,4 +31,5 @@
 import static com.framsticks.util.lang.Containers.filterInstanceof;
 import com.framsticks.util.swing.TreeNodeUtils;
+import static com.framsticks.core.InstanceUtils.*;
 
 /**
@@ -73,8 +76,7 @@
 		assert p.getInstance().isActive();
 		log.debug("fetching: " + p);
-		p.getInstance().fetchValues(p, new StateFunctor() {
-			@Override
-			public void call(Exception e) {
-				//TODO removing should stay here
+		p.getInstance().fetchValues(p, new AbstractStateFunctor() {
+			@Override
+			public void call() {
 				// reactForFetchResult(p, e);
 			}
@@ -140,5 +142,5 @@
 		assert p.getInstance().isActive();
 		log.debug("updating children of " + this);
-		AccessInterface access = p.getInstance().bindAccess(p.getTop());
+		AccessInterface access = InstanceUtils.bindAccess(p.getInstance(), p.getTop());
 		if (access == null) {
 			return;
@@ -199,11 +201,7 @@
 					return;
 				}
-				p.getInstance().resolve(updated, new Future<Path>() {
+				p.getInstance().resolve(updated, new Future<Path>(Logging.logger(log, "resolve and select", TreeNode.this)) {
 					@Override
-					public void result(final Path result, Exception e) {
-						if (Logging.log(log, "resolve and select", TreeNode.this, e)) {
-							return;
-						}
-
+					protected void result(Path result) {
 						fetch(result);
 						postUpdatePath(result);
@@ -231,8 +229,5 @@
 			return;
 		}
-		AccessInterface access = p.getInstance().bindAccess(p);
-		if (access == null) {
-			return;
-		}
+		AccessInterface access = InstanceUtils.bindAccess(p);
 
 		final String tooltip = new TooltipConstructor()
@@ -309,5 +304,5 @@
 			@Override
 			public void run() {
-				AccessInterface access = p.getInstance().bindAccess(p);
+				AccessInterface access = InstanceUtils.bindAccess(p);
 				panel.pullValuesFromLocalToUser(access);
 
@@ -501,31 +496,27 @@
 			return;
 		}
-		final Map<ValueControl, Object> changes = localChanges;
+		Map<ValueControl, Object> changes = localChanges;
 		localChanges = null;
-		instanceAtFrame.getInstance().dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				for (Map.Entry<ValueControl, Object> e : changes.entrySet()) {
-					final ValueControl key = e.getKey();
-					final Path p = path;
-					instanceAtFrame.getInstance().storeValue(p, e.getKey().getParam(), e.getValue(), new StateFunctor() {
+		final Holder<Integer> counter = new Holder<>(changes.size());
+		final Path p = path;
+
+		for (Map.Entry<ValueControl, Object> e : localChanges.entrySet()) {
+			storeValue(p, e.getKey().getParam(), e.getValue(), new AbstractStateFunctor() {
+				@Override
+				public void call() {
+					counter.set(counter.get() - 1);
+					if (counter.get() != 0) {
+						return;
+					}
+					log.debug("applied changes for: " + p);
+					frame.dispatch(new RunAt<Frame>() {
 						@Override
-						public void call(Exception e) {
-							changes.remove(key);
-							if (!changes.isEmpty()) {
-								return;
-							}
-							log.debug("applied changes for: " + p);
-							frame.dispatch(new RunAt<Frame>() {
-								@Override
-								public void run() {
-									fillPanelWithValues();
-								}
-							});
+						public void run() {
+							fillPanelWithValues();
 						}
 					});
 				}
-			}
-		});
+			});
+		}
 	}
 }
Index: /java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 96)
@@ -8,6 +8,7 @@
 import com.framsticks.params.ValueParam;
 import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.Logging;
-import com.framsticks.util.StateFunctor;
+import com.framsticks.util.dispatching.Future;
 import com.framsticks.util.dispatching.RunAt;
 
@@ -67,8 +68,14 @@
 					@Override
 					public void run() {
-						path.getInstance().call(path, getParam(), arguments.toArray(), new StateFunctor() {
+						path.getInstance().call(path, getParam(), arguments.toArray(), new Future<Object>() {
+
 							@Override
-							public void call(Exception e) {
+							public void handle(FramsticksException e) {
 								Logging.log(log, "call procedure", path, e);
+							}
+
+							@Override
+							public void result(Object result) {
+
 							}
 						});
Index: /java/main/src/main/java/com/framsticks/gui/windows/console/ConsoleFrame.java
===================================================================
--- /java/main/src/main/java/com/framsticks/gui/windows/console/ConsoleFrame.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/gui/windows/console/ConsoleFrame.java	(revision 96)
@@ -161,5 +161,5 @@
 		}
 		String commandText = commandLine.getText();
-		Pair<String, String> command = Strings.splitIntoPair(commandText, ' ', "\n");
+		Pair<String, String> command = Strings.splitIntoPair(commandText, ' ', "");
 		Request request = Request.createRequestByTypeString(command.first);
 		if (request == null) {
Index: /java/main/src/main/java/com/framsticks/hosting/InstanceClient.java
===================================================================
--- /java/main/src/main/java/com/framsticks/hosting/InstanceClient.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/hosting/InstanceClient.java	(revision 96)
@@ -1,13 +1,19 @@
 package com.framsticks.hosting;
+
+import static com.framsticks.util.lang.Strings.assureNotEmpty;
 
 import com.framsticks.communication.*;
 import com.framsticks.communication.queries.ApplicationRequest;
+import com.framsticks.communication.queries.CallRequest;
 import com.framsticks.communication.queries.GetRequest;
 import com.framsticks.communication.queries.InfoRequest;
+import com.framsticks.communication.queries.SetRequest;
 import com.framsticks.core.Instance;
+import com.framsticks.core.InstanceUtils;
 import com.framsticks.core.Path;
 import com.framsticks.params.*;
+import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.parsers.Savers;
-import com.framsticks.core.LocalInstance;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.dispatching.AbstractJoinable;
 import com.framsticks.util.dispatching.Dispatching;
@@ -16,10 +22,9 @@
 import com.framsticks.util.dispatching.JoinableParent;
 import com.framsticks.util.dispatching.JoinableState;
+import static com.framsticks.core.InstanceUtils.*;
 
 import java.net.Socket;
-import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
-import com.framsticks.util.dispatching.RunAt;
 
 /**
@@ -28,43 +33,55 @@
 public class InstanceClient extends AbstractJoinable implements RequestHandler, JoinableParent {
 
-	protected final LocalInstance instance;
+	protected final Server server;
+	protected final Instance instance;
 	protected final ServerConnection connection;
 
-	public InstanceClient(LocalInstance instance, Socket socket) {
-		this.instance = instance;
-		connection = new ServerConnection(socket, this);
+	public InstanceClient(Server server, Socket socket) {
+		this.server = server;
+		this.instance = server.hosted;
+		this.connection = new ServerConnection(socket, this);
 	}
 
 	@Override
-	public String toString() {
-		return instance + "|" + connection.toString();
+	public String getName() {
+		return connection + " to " + server;
 	}
 
 	@Override
 	public void handle(final ApplicationRequest request, final ResponseCallback<?> responseCallback) {
-		instance.dispatch(new RunAt<Instance>() {
+		assureNotEmpty(request.getPath());
+
+		resolve(instance, request.getPath(), new Future<Path>(responseCallback) {
 			@Override
-			public void run() {
-				final Path path = instance.getPath(request.getPath());
-				if (!path.isResolved(request.getPath())) {
-					responseCallback.process(new Response(false, "\"invalid path\"", null));
+			protected void result(final Path path) {
+
+				// final AccessInterface access = instance.prepareAccess(path);
+				final AccessInterface access = instance.prepareAccess(path.getTop().getParam());
+
+				if (request instanceof SetRequest) {
+					SetRequest set = (SetRequest) request;
+					//TODO Proxy - here is break of chain, instance should have hosted
+					//hosted set
+					AccessInterface access2 = InstanceUtils.bindAccess(path);
+					int flag = access2.set(set.getField(), set.getValue());
+
+					responseCallback.process(new Response(true, Flags.write(flag, null), null));
 					return;
 				}
+
 				if (request instanceof GetRequest) {
-					instance.findInfo(path, new Future<FramsClass>() {
+					InstanceUtils.findInfo(path, new Future<FramsClass>(responseCallback) {
 						@Override
-						public void result(FramsClass result, Exception e) {
+						protected void result(FramsClass result) {
 							if (result == null) {
-								responseCallback.process(new Response(false, "\"failed to find info for access bind\"", null));
-								return;
+								throw new FramsticksException().msg("failed to find info for access bind");
 							}
 							List<File> files = new LinkedList<File>();
-							AccessInterface access = instance.bindAccess(path);
+							AccessInterface access = bindAccess(path);
 
 							if (access == null) {
+								throw new FramsticksException().msg("failed to bind access");
+							}
 
-								responseCallback.process(new Response(false, "\"failed to bind access\"", null));
-								return;
-							}
 							ListSink sink = new ListSink();
 							access.save(sink);
@@ -75,22 +92,36 @@
 					return;
 				}
-				if (request instanceof InfoRequest) {
-					instance.findInfo(path, new Future<FramsClass>() {
+				if (request instanceof CallRequest) {
+					final CallRequest callRequest = (CallRequest) request;
+					instance.call(path, access.getFramsClass().getParamEntry(callRequest.getProcedure(), ProcedureParam.class), callRequest.getArguments().toArray(), new Future<Object>(responseCallback) {
 						@Override
-						public void result(FramsClass result, Exception e) {
-							if (result == null) {
-								responseCallback.process(new Response(false, "\"info not found\"", null));
-								return;
+						protected void result(Object result) {
+							ListSink sink = new ListSink();
+							sink.print("Result:").breakLine();
+							sink.print("value:").print("[");
+							if (result != null) {
+								sink.print(result);
 							}
-							ListSink sink = new ListSink();
-							Savers.saveFramsClass(sink, result);
-							List<File> files = new ArrayList<File>();
-							files.add(new File(path.getTextual(), new ListSource(sink.getOut())));
-							responseCallback.process(new Response(true, null, files));
+							sink.print("]");
+
+							responseCallback.process(new Response(true, "", File.single(new File("", new ListSource(sink.getOut())))));
 						}
 					});
 					return;
 				}
-				responseCallback.process(new Response(false, "invalid", null));
+				if (request instanceof InfoRequest) {
+					findInfo(path, new Future<FramsClass>(responseCallback) {
+						@Override
+						protected void result(FramsClass result) {
+							if (result == null) {
+								throw new FramsticksException().msg("info not found");
+							}
+							responseCallback.process(new Response(true, null, File.single(new File(path.getTextual(), new ListSource(Savers.saveFramsClass(new ListSink(), result).getOut())))));
+						}
+					});
+					return;
+				}
+
+				throw new FramsticksException().msg("invalid request type: " + request.getCommand());
 			}
 		});
@@ -122,3 +153,4 @@
 	}
 
+
 }
Index: /java/main/src/main/java/com/framsticks/hosting/Server.java
===================================================================
--- /java/main/src/main/java/com/framsticks/hosting/Server.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/hosting/Server.java	(revision 96)
@@ -0,0 +1,220 @@
+package com.framsticks.hosting;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+import com.framsticks.core.Instance;
+import com.framsticks.params.annotations.AutoAppendAnnotation;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.AbstractJoinable;
+import com.framsticks.util.dispatching.Dispatching;
+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;
+import com.framsticks.util.dispatching.Task;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import com.framsticks.util.dispatching.Thread;
+
+@FramsClassAnnotation
+public class Server extends AbstractJoinable implements JoinableParent {
+
+	private final static Logger log = Logger.getLogger(Server.class);
+
+	protected int port;
+
+	protected ServerSocket acceptSocket;
+	protected Instance hosted;
+	protected final JoinableCollection<InstanceClient> clients = new JoinableCollection<InstanceClient>();
+
+	public static class Accept {
+	};
+
+	protected Thread<Accept> acceptThread = new Thread<>();
+
+	/**
+	 *
+	 */
+	public Server() {
+		log.debug("created server");
+		port = 9009;
+	}
+
+	/**
+	 * @return the port
+	 */
+	@ParamAnnotation
+	public int getPort() {
+		return port;
+	}
+
+	/**
+	 * @param port the port to set
+	 */
+	@ParamAnnotation
+	public void setPort(int port) {
+		this.port = port;
+	}
+
+	@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);
+		}
+		finish();
+	}
+
+	/**
+	 * @return the hosted
+	 */
+	public Instance getHosted() {
+		return hosted;
+	}
+
+	@AutoAppendAnnotation
+	public void setHosted(Instance hosted) {
+		if (this.hosted != null) {
+			throw new FramsticksException().msg("hosted instance is already set").arg("current", this.hosted);
+		}
+		this.hosted = hosted;
+		acceptThread.setName(hosted.getName() + " acceptor");
+		clients.setObservableName(hosted.getName() + " clients");
+	}
+
+	@Override
+	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);
+	}
+
+	@Override
+	@ParamAnnotation
+	public String getName() {
+		return hosted != null ? hosted.getName() : "server";
+	}
+
+	protected void acceptNext() {
+		if (!isRunning()) {
+			log.debug("server is not in running state, aborting accepting");
+			return;
+		}
+		acceptThread.dispatch(new RunAt<Accept>() {
+			@Override
+			public void run() {
+				try {
+					log.debug("accepting");
+					final Socket socket = acceptSocket.accept();
+					assert socket != null;
+					log.debug("accepted socket: " + socket.getInetAddress().getHostAddress());
+					hosted.dispatch(new RunAt<Instance>() {
+						@Override
+						public void run() {
+							InstanceClient client = new InstanceClient(Server.this, socket);
+							clients.add(client);
+							log.info("client connected: " + client);
+						}
+					});
+				} catch (IOException e) {
+					log.log((isRunning() ? Level.ERROR : Level.DEBUG), "failed to accept socket: " + e);
+				}
+				acceptNext();
+			}
+		});
+	}
+
+	protected void tryBind(int when) {
+		acceptThread.dispatch(new Task<Accept>(when) {
+			@Override
+			public void run() {
+				try {
+					acceptSocket.bind(new InetSocketAddress(port));
+					log.debug("started accepting on port " + port);
+					acceptNext();
+					return;
+				} catch (IOException e) {
+					log.warn("failed to accept on port " + port + " (repeating): " + e);
+				}
+				tryBind(1000);
+			}
+		});
+	}
+
+	@Override
+	protected void joinableFinish() {
+
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.join(acceptThread);
+		Dispatching.join(hosted);
+		Dispatching.join(clients);
+	}
+
+	// @Override
+	// public FramsClass getInfoFromCache(String id) {
+	//	assert isActive();
+	//	if (id == null) {
+	//		return null;
+	//	}
+	//	FramsClass cached = registry.getFramsClass(id);
+	//	if (cached != null) {
+	//		return cached;
+	//	}
+	//	try {
+	//		Class<?> nativeClass = Class.forName(id);
+	//		FramsClass framsClass = FramsClass.build().forClass(nativeClass);
+
+	//		if (!framsClass.getId().equals(id)) {
+	//			log.error("no matching id");
+	//			return null;
+	//		}
+
+	//		registry.registerReflectedClass(null, id, nativeClass);
+	//		registry.putFramsClass(framsClass);
+	//		return framsClass;
+	//	} catch (ClassNotFoundException ignored) {
+	//	} catch (ConstructionException e) {
+	//		log.error("failed to use info from cache: " + e);
+	//	}
+
+	//	return null;
+	// }
+
+	// @Override
+	// protected void fetchInfo(Path path, Future<FramsClass> future) {
+	//	assert isActive();
+
+	//	FramsClass framsClass = getInfoFromCache(path.getTop().getObject().getClass().getCanonicalName());
+	//	if (framsClass == null) {
+	//		log.error("failed to create frams class for: " + path.getTop().getObject().getClass());
+	//		future.result(null, new Exception());
+	//		return;
+	//	}
+	//	future.result(framsClass, null);
+	// }
+}
Index: va/main/src/main/java/com/framsticks/hosting/ServerInstance.java
===================================================================
--- /java/main/src/main/java/com/framsticks/hosting/ServerInstance.java	(revision 95)
+++ 	(revision )
@@ -1,114 +1,0 @@
-package com.framsticks.hosting;
-
-import com.framsticks.core.*;
-import com.framsticks.params.ConstructionException;
-import com.framsticks.params.FramsClass;
-import com.framsticks.core.LocalInstance;
-import com.framsticks.util.dispatching.Dispatching;
-import com.framsticks.util.dispatching.Future;
-import com.framsticks.util.dispatching.Joinable;
-import com.framsticks.util.dispatching.JoinableParent;
-import com.framsticks.util.dispatching.JoinableState;
-
-import org.apache.log4j.Logger;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class ServerInstance extends LocalInstance implements JoinableParent {
-
-	private final static Logger log = Logger.getLogger(ServerInstance.class.getName());
-
-	Entity hosted;
-
-	public ServerInstance() {
-	}
-
-	// @Override
-	// public void configure(Configuration config) {
-	//	super.configure(config);
-
-	//	Configuration hostedConfig = config.subset("hosted.entity");
-	//	hosted = Program.configureEntity(hostedConfig);
-	//	if (hosted == null) {
-	//		log.fatal("failed to create hosted entity");
-	//		return;
-	//	}
-	//	hosted.setName("hosted");
-	//	hosted.configure(hostedConfig);
-	//	root = new Node(Param.build().name("root").id("root").type("o" + hosted.getClass().getCanonicalName()), hosted);
-	// }
-
-	@Override
-	public FramsClass getInfoFromCache(String id) {
-		assert isActive();
-		if (id == null) {
-			return null;
-		}
-		FramsClass cached = registry.getFramsClass(id);
-		if (cached != null) {
-			return cached;
-		}
-		try {
-			Class<?> nativeClass = Class.forName(id);
-			FramsClass framsClass = FramsClass.build().forClass(nativeClass);
-
-			if (!framsClass.getId().equals(id)) {
-				log.error("no matching id");
-				return null;
-			}
-
-			registry.registerReflectedClass(null, id, nativeClass);
-			registry.putFramsClass(framsClass);
-			return framsClass;
-		} catch (ClassNotFoundException ignored) {
-		} catch (ConstructionException e) {
-			log.error("failed to use info from cache: " + e);
-		}
-
-		return null;
-	}
-
-	@Override
-	protected void fetchInfo(Path path, Future<FramsClass> future) {
-		assert isActive();
-
-		FramsClass framsClass = getInfoFromCache(path.getTop().getObject().getClass().getCanonicalName());
-		if (framsClass == null) {
-			log.error("failed to create frams class for: " + path.getTop().getObject().getClass());
-			future.result(null, new Exception());
-			return;
-		}
-		future.result(framsClass, null);
-
-	}
-
-	@Override
-	protected void tryRegisterOnChangeEvents(Path path) {
-	}
-
-	@Override
-	public void childChangedState(Joinable joinable, JoinableState state) {
-		proceedToState(state);
-	}
-
-	@Override
-	protected void joinableStart() {
-		super.joinableStart();
-		assert hosted != null;
-		Dispatching.use(hosted, this);
-	}
-
-	@Override
-	protected void joinableInterrupt() {
-		super.joinableInterrupt();
-		Dispatching.drop(hosted, this);
-	}
-
-	@Override
-	protected void joinableJoin() throws InterruptedException {
-		Dispatching.join(hosted);
-		super.joinableJoin();
-	}
-
-}
Index: /java/main/src/main/java/com/framsticks/params/AccessInterface.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/AccessInterface.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/AccessInterface.java	(revision 96)
@@ -75,5 +75,5 @@
 	FramsClass getFramsClass();
 
-	boolean tryAutoAppend(Object object);
+	void tryAutoAppend(Object object);
 
 
Index: /java/main/src/main/java/com/framsticks/params/Flags.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/Flags.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/Flags.java	(revision 96)
@@ -50,5 +50,5 @@
 
 	public static String write(int flags, String empty) {
-		Delimeted d = new Delimeted("+", empty);
+		Delimeted<String> d = new Delimeted<String>("+", empty);
 		try {
 			for (Field f : Flags.class.getDeclaredFields()) {
Index: /java/main/src/main/java/com/framsticks/params/FramsClass.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/FramsClass.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/FramsClass.java	(revision 96)
@@ -130,5 +130,5 @@
 	}
 
-	public <T extends Param> T castedParam(@Nonnull final Param param, @Nonnull final Class<T> type, Object name) {
+	public @Nonnull <T extends Param> T castedParam(@Nonnull final Param param, @Nonnull final Class<T> type, Object name) {
 		if (param == null) {
 			// return null;
@@ -149,5 +149,5 @@
 	 * @return the param entry
 	 */
-	public <T extends Param> T getParamEntry(final int i, @Nonnull final Class<T> type) {
+	public @Nonnull <T extends Param> T getParamEntry(final int i, @Nonnull final Class<T> type) {
 		return castedParam(getParam(i), type, i);
 	}
@@ -160,5 +160,5 @@
 	 * @return the param entry
 	 */
-	public <T extends Param> T getParamEntry(@Nonnull final String id, @Nonnull final Class<T> type) {
+	public @Nonnull <T extends Param> T getParamEntry(@Nonnull final String id, @Nonnull final Class<T> type) {
 		return castedParam(getParam(id), type, id);
 	}
Index: /java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java	(revision 96)
@@ -22,4 +22,5 @@
 import com.framsticks.parsers.Loaders;
 import com.framsticks.util.Builder;
+import com.framsticks.util.Misc;
 import com.framsticks.util.lang.Containers;
 import com.framsticks.util.lang.Strings;
@@ -78,13 +79,13 @@
 			// TODO: future support for enum
 			// if (cl.isEnum()) {
-			// 	Class<? extends Enum<?>> enumType = (Class<? extends Enum<?>>) cl;
-			// 	Enum<?>[] enums = enumType.getEnumConstants();
-			// 	StringBuilder b = new StringBuilder();
-
-			// 	b.append("d 0 ").append(enums.length - 1).append(" 0 ");
-			// 	for (Enum<?> e : enums) {
-			// 		b.append("~").append(e.name());
-			// 	}
-			// 	return b.toString();
+			//	Class<? extends Enum<?>> enumType = (Class<? extends Enum<?>>) cl;
+			//	Enum<?>[] enums = enumType.getEnumConstants();
+			//	StringBuilder b = new StringBuilder();
+
+			//	b.append("d 0 ").append(enums.length - 1).append(" 0 ");
+			//	for (Enum<?> e : enums) {
+			//		b.append("~").append(e.name());
+			//	}
+			//	return b.toString();
 			// }
 			if (cl.equals(Integer.class) || cl.equals(int.class)) {
@@ -125,5 +126,7 @@
 		}
 
-		builder.resultType(induceParamType(Param.build(), method.getGenericReturnType()).finish(ValueParam.class));
+		if (!method.getReturnType().equals(Void.TYPE)) {
+			builder.resultType(induceParamType(Param.build(), method.getGenericReturnType()).finish(ValueParam.class));
+		}
 
 		List<ValueParam> arguments = new ArrayList<>();
@@ -337,4 +340,8 @@
 	}
 
+	@Override
+	public String toString() {
+		return "FramsClassBuilder for " + Misc.returnNotNull(id, "<not yet known>");
+	}
 
 }
Index: /java/main/src/main/java/com/framsticks/params/ListAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 96)
@@ -79,6 +79,6 @@
 	//TODO it could actually be used also
 	@Override
-	public boolean tryAutoAppend(Object object) {
-		return false;
+	public void tryAutoAppend(Object object) {
+		throw new InvalidOperationException();
 	}
 
Index: /java/main/src/main/java/com/framsticks/params/Param.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/Param.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/Param.java	(revision 96)
@@ -17,5 +17,5 @@
  */
 @Immutable
-@FramsClassAnnotation(id = "prop", name = "prop")
+@FramsClassAnnotation(id = "prop", name = "prop", order = {"id", "name", "type", "flags", "help", "group", "extra"})
 public abstract class Param {
 
@@ -33,9 +33,9 @@
 
 	/** The getFlags stored as a bit sum. */
-	protected final Integer flags;
+	protected final int flags;
 
 	//TODO
 	/** The variable determining whether the parameter is an extra parameter. */
-	protected final Integer extra;
+	protected final int extra;
 
 	public Param(ParamBuilder builder) {
@@ -68,9 +68,10 @@
 	}
 
-	@ParamAnnotation
+	@ParamAnnotation(def = "0")
 	public Integer getFlags() {
 		return flags;
 	}
 
+	@ParamAnnotation(id = "type")
 	public abstract String getFramsTypeName();
 
@@ -92,5 +93,5 @@
 
 	public boolean hasFlag(int flag) {
-		return flags != null && (flags & flag) != 0;
+		return (flags & flag) != 0;
 	}
 
Index: /java/main/src/main/java/com/framsticks/params/ParamBuilder.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/ParamBuilder.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/ParamBuilder.java	(revision 96)
@@ -6,4 +6,5 @@
 import com.framsticks.util.Builder;
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.Misc;
 import com.framsticks.util.lang.Strings;
 
@@ -46,5 +47,5 @@
 
 	/** The flags stored as a bit sum. */
-	private Integer flags = 0;
+	private int flags = 0;
 
 	/** The parameter name. */
@@ -63,5 +64,5 @@
 	private Object def;
 
-	private Integer extra;
+	private int extra = 0;
 
 	String containedTypeName;
@@ -179,5 +180,5 @@
 		try {
 			if (paramType == null) {
-				throw new FramsticksException().msg("trying to finish incomplete param");
+				throw new FramsticksException().msg("trying to finish incomplete param while type is missing");
 			}
 			return paramType.getConstructor(ParamBuilder.class).newInstance(this);
@@ -214,5 +215,5 @@
 
 	@ParamAnnotation
-	public ParamBuilder flags(Integer flags) {
+	public ParamBuilder flags(int flags) {
 		this.flags = flags;
 		return this;
@@ -359,5 +360,5 @@
 	 */
 	@ParamAnnotation
-	public Integer getFlags() {
+	public int getFlags() {
 		return flags;
 	}
@@ -385,5 +386,5 @@
 
 	@ParamAnnotation(id = "xtra")
-	public Integer getExtra() {
+	public int getExtra() {
 		return extra;
 	}
@@ -397,5 +398,5 @@
 
 	@ParamAnnotation(id = "xtra")
-	public ParamBuilder extra(Integer extra) {
+	public ParamBuilder extra(int extra) {
 		this.extra = extra;
 		return this;
@@ -517,5 +518,9 @@
 		}
 		String result = Strings.collapse(matcher.group(1));
-		resultType = (result != null) ? parseProcedureTypePart(result, null) : null;
+		if (result != null) {
+			resultType = Param.build().type(result).finish(ValueParam.class);
+		} else {
+			resultType = null;
+		}
 		String arguments = matcher.group(2);
 		if (!Strings.notEmpty(arguments)) {
@@ -524,15 +529,14 @@
 		int number = 0;
 		for (String a : arguments.split(",")) {
+			ParamBuilder arg = Param.build();
+
 			int space = a.indexOf(' ');
-			String type;
-			String name;
 			if (space == -1) {
-				type = a;
-				name = "arg" + number;
+				arg.type(a).id("arg" + number);
 			} else {
-				type = a.substring(0, space);
-				name = a.substring(space + 1);
-			}
-			argumentsType.add(parseProcedureTypePart(type, name));
+				String name = a.substring(space + 1);
+				arg.type(a.substring(0, space)).id(name).name(name);
+			}
+			argumentsType.add(arg.finish(ValueParam.class));
 			++number;
 		}
@@ -546,4 +550,9 @@
 		return this;
 	}
+
+	@Override
+	public String toString() {
+		return "ParamBuilder for " + Misc.returnNotNull(id, "<not yet known>");
+	}
 }
 
Index: /java/main/src/main/java/com/framsticks/params/PropertiesAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/PropertiesAccess.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/PropertiesAccess.java	(revision 96)
@@ -91,6 +91,6 @@
 
 	@Override
-	public boolean tryAutoAppend(Object object) {
-		return false;
+	public void tryAutoAppend(Object object) {
+		throw new InvalidOperationException();
 	}
 
Index: /java/main/src/main/java/com/framsticks/params/ReflectionAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/ReflectionAccess.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/ReflectionAccess.java	(revision 96)
@@ -378,18 +378,23 @@
 
 	@Override
-	public boolean tryAutoAppend(Object value) {
+	public void tryAutoAppend(Object value) {
 		assert object != null;
-		for (Method m : backend.autoAppendMethods) {
-			if (m.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
-				try {
-					log.trace("auto appending with value " + value + " with method " + m);
-					m.invoke(object, value);
-					return true;
-				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | FramsticksException e) {
-					throw new FramsticksException().msg("failed to auto append").cause(e).arg("value", value).arg("into object", object).arg("with method", m);
-				}
-			}
-		}
-		return false;
+		try {
+			for (Method m : backend.autoAppendMethods) {
+				if (m.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
+					try {
+						log.trace("auto appending with value " + value + " with method " + m);
+						m.invoke(object, value);
+						return;
+					} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | FramsticksException e) {
+						throw new FramsticksException().msg("failed to auto append").cause(e).arg("with method", m);
+					}
+				}
+			}
+			throw new FramsticksException().msg("no method found to append");
+		} catch (FramsticksException e) {
+			throw e.arg("value", value).arg("into object", object);
+		}
+
 	}
 
Index: /java/main/src/main/java/com/framsticks/params/Registry.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/Registry.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/Registry.java	(revision 96)
@@ -46,4 +46,11 @@
 		associate(javaClass, putFramsClass(FramsClass.build().forClass(javaClass)));
 		return this;
+	}
+
+	public FramsClass registerReflectedIfNeeded(Class<?> javaClass) {
+		if (!javaToFramsAssociation.containsKey(javaClass)) {
+			registerAndBuild(javaClass);
+		}
+		return javaToFramsAssociation.get(javaClass);
 	}
 
Index: /java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 96)
@@ -7,4 +7,6 @@
 
 import org.apache.log4j.Logger;
+
+import com.framsticks.util.UnimplementedException;
 
 /**
@@ -177,5 +179,6 @@
 	@Override
 	public void copyFrom(AccessInterface src) {
-		clearValues();
+		throw new UnimplementedException();
+		// clearValues();
 		//TODO: iterate over self, and pull from src
 		/*
@@ -185,7 +188,4 @@
 		*/
 	}
-
-
-
 
 	@Override
@@ -195,5 +195,5 @@
 		for (PrimitiveParam<?> p : filterInstanceof(framsClass.getParamEntries(), PrimitiveParam.class)) {
 			Object value = get(p, Object.class);
-			if (value == null) {
+			if ((value == null) || value.equals(p.getDef(Object.class))) {
 				continue;
 			}
Index: /java/main/src/main/java/com/framsticks/params/SinkInterface.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/SinkInterface.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/SinkInterface.java	(revision 96)
@@ -5,7 +5,7 @@
  */
 public interface SinkInterface {
-    SinkInterface print(String str);
-    SinkInterface print(Object obj);
-    void breakLine();
-    void close();
+	SinkInterface print(String str);
+	SinkInterface print(Object obj);
+	void breakLine();
+	void close();
 }
Index: /java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java
===================================================================
--- /java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java	(revision 96)
@@ -7,4 +7,5 @@
 import java.util.List;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
@@ -16,4 +17,5 @@
 	private final ValueParam resultType;
 	private final List<ValueParam> argumentsType;
+	private final String signatureString;
 
 	/**
@@ -24,4 +26,27 @@
 		resultType = builder.getResultType();
 		argumentsType = builder.getArgumentsType();
+
+		StringBuilder b = new StringBuilder().append("p");
+
+		if (resultType != null) {
+			b.append(" ").append(resultType.getFramsTypeName());
+		}
+		b.append("(");
+		boolean first = true;
+		for (ValueParam arg : argumentsType) {
+			if (first) {
+				first = false;
+			} else {
+				b.append(", ");
+			}
+
+			b.append(arg.getFramsTypeName());
+			if (arg.getName() != null) {
+				b.append(" ").append(arg.getName());
+			}
+		}
+		b.append(")");
+
+		signatureString = b.toString();
 		assert argumentsType != null;
 	}
@@ -32,5 +57,5 @@
 	}
 
-	public ValueParam getResultType() {
+	public @Nullable ValueParam getResultType() {
 		return resultType;
 	}
@@ -42,5 +67,5 @@
 	@Override
 	public String getFramsTypeName() {
-		return "p";
+		return signatureString;
 	}
 
Index: /java/main/src/main/java/com/framsticks/parsers/Loaders.java
===================================================================
--- /java/main/src/main/java/com/framsticks/parsers/Loaders.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/parsers/Loaders.java	(revision 96)
@@ -32,8 +32,6 @@
 					return;
 				}
-				if (framsClassAccess.select(builder).tryAutoAppend(object)) {
-					return;
-				}
-				throw new ConstructionException().msg("failed to interpretate object").arg("object", object);
+				framsClassAccess.select(builder).tryAutoAppend(object);
+				// throw new ConstructionException().msg("failed to interpretate object").arg("object", object);
 
 			}
Index: /java/main/src/main/java/com/framsticks/parsers/Savers.java
===================================================================
--- /java/main/src/main/java/com/framsticks/parsers/Savers.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/parsers/Savers.java	(revision 96)
@@ -8,5 +8,5 @@
  */
 public class Savers {
-	public static void saveFramsClass(SinkInterface sink, FramsClass framsClass) {
+	public static <S extends SinkInterface> S saveFramsClass(S sink, FramsClass framsClass) {
 
 		AccessInterface framsClassAccess = new ReflectionAccess(FramsClass.class);
@@ -18,4 +18,5 @@
 			paramAccess.save(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 95)
+++ /java/main/src/main/java/com/framsticks/parsers/XmlLoader.java	(revision 96)
@@ -98,7 +98,5 @@
 
 			for (Object child : childrenObjects) {
-				if (!access.tryAutoAppend(child)) {
-					throw new FramsticksException().msg("failed to auto append").arg("child", child).arg("parent", object);
-				}
+				access.tryAutoAppend(child);
 			}
 		}
Index: /java/main/src/main/java/com/framsticks/portals/Portal.java
===================================================================
--- /java/main/src/main/java/com/framsticks/portals/Portal.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/portals/Portal.java	(revision 96)
@@ -4,4 +4,5 @@
 import com.framsticks.core.AbstractInstanceListener;
 import com.framsticks.core.Instance;
+import com.framsticks.core.InstanceUtils;
 import com.framsticks.core.Path;
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -61,8 +62,8 @@
 					@Override
 					public void run() {
-						instance.resolve(path, new Future<Path>() {
+						InstanceUtils.resolve(instance, path, new Future<Path>(Logging.logger(log, "resolve", path)) {
 							@Override
-							public void result(Path result, Exception e) {
-								Logging.log(log, "resolve", path, e);
+							public void result(Path result) {
+								Logging.log(log, "resolve", path, null);
 							}
 						});
Index: /java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java
===================================================================
--- /java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java	(revision 96)
@@ -1,4 +1,5 @@
 package com.framsticks.remote;
 
+import static com.framsticks.core.InstanceUtils.*;
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
@@ -8,4 +9,6 @@
 import com.framsticks.core.Instance;
 import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.Logging;
 import com.framsticks.util.StateFunctor;
 import com.framsticks.util.Stopwatch;
@@ -36,5 +39,5 @@
 		assert instance.isActive();
 		log.info("recursively fetched in " + stopwatch);
-		stateFunctor.call(null);
+		stateFunctor.call();
 	}
 
@@ -44,5 +47,5 @@
 			log.warn("path " + path + " is not resolved - skipping");
 		} else {
-			AccessInterface access = instance.bindAccess(path);
+			AccessInterface access = bindAccess(path);
 			FramsClass framsClass = access.getFramsClass();
 			assert framsClass != null;
@@ -50,5 +53,5 @@
 				Object child = access.get(p, Object.class);
 				final Path childPath = path.appendNode(new Node(p, child));
-				if (childPath.isResolved() && instance.getInfoFromCache(childPath) != null) {
+				if (childPath.isResolved() && getInfoFromCache(childPath) != null) {
 					++dispatched;
 					instance.dispatch(new RunAt<Instance>() {
@@ -61,12 +64,8 @@
 				}
 				++dispatched;
-				instance.resolve(childPath, new Future<Path>() {
+				instance.resolve(childPath, new Future<Path>(Logging.logger(log, "resolve", RecursiveFetcher.this)) {
 					@Override
-					public void result(Path result, Exception e) {
+					protected void result(Path result) {
 						assert instance.isActive();
-						if (e != null) {
-							log.error(e);
-							return;
-						}
 						fetch(result);
 					}
@@ -83,10 +82,11 @@
 		instance.fetchValues(path, new StateFunctor() {
 			@Override
-			public void call(Exception e) {
-				if (e != null) {
-					log.error("failed to fetch values for " + path + ": " + e);
-					process(null);
-					return;
-				}
+			public void handle(FramsticksException e) {
+				log.error("failed to fetch values for " + path + ": " + e);
+				process(null);
+			}
+
+			@Override
+			public void call() {
 				process(path);
 			}
Index: /java/main/src/main/java/com/framsticks/remote/RemoteInstance.java
===================================================================
--- /java/main/src/main/java/com/framsticks/remote/RemoteInstance.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/remote/RemoteInstance.java	(revision 96)
@@ -2,9 +2,12 @@
 
 import com.framsticks.communication.*;
+import com.framsticks.communication.queries.CallRequest;
 import com.framsticks.communication.queries.GetRequest;
 import com.framsticks.communication.queries.InfoRequest;
 import com.framsticks.communication.queries.SetRequest;
-import com.framsticks.communication.util.LoggingSubscriptionCallback;
+import com.framsticks.core.AbstractInstance;
+import com.framsticks.core.InstanceUtils;
 import com.framsticks.core.ListChange;
+import com.framsticks.core.Node;
 import com.framsticks.core.Path;
 import com.framsticks.params.*;
@@ -17,4 +20,5 @@
 import com.framsticks.util.*;
 import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 import com.framsticks.util.dispatching.Future;
 import com.framsticks.util.dispatching.Joinable;
@@ -24,6 +28,9 @@
 import com.framsticks.util.lang.Pair;
 import com.framsticks.util.dispatching.RunAt;
+import static com.framsticks.core.InstanceUtils.*;
 
 import java.util.*;
+
+import javax.annotation.Nonnull;
 
 import org.apache.log4j.Logger;
@@ -33,9 +40,8 @@
  */
 @FramsClassAnnotation
-public class RemoteInstance extends Instance implements JoinableParent {
+public class RemoteInstance extends AbstractInstance implements JoinableParent {
 
 	private final static Logger log = Logger.getLogger(RemoteInstance.class.getName());
 
-	protected Path simulator;
 	protected ClientConnection connection;
 
@@ -64,68 +70,31 @@
 	}
 
+	protected void onProtocolVersionNegotiated() {
+	}
+
+
 	public void setConnection(final ClientConnection connection) {
 		this.connection = connection;
-		this.connection.setConnectedFunctor(new StateFunctor() {
-			@Override
-			public void call(Exception e) {
-				if (e != null) {
-					fireRun(e);
-					return;
-				}
-				connection.negotiateProtocolVersion(new StateFunctor() {
+		final ExceptionResultHandler failure = new ExceptionResultHandler() {
+			@Override
+			public void handle(FramsticksException exception) {
+				log.fatal("failed to establish connection: ", exception);
+				// log.fatal("unsupported protocol version!\n minimal version is: " + "\nmanager protocol is: " + connection.getProtocolVersion());
+				Dispatching.drop(connection, RemoteInstance.this);
+				fireRun(exception);
+			}
+		};
+
+		this.connection.setConnectedFunctor(new AbstractStateFunctor(failure) {
+			@Override
+			public void call() {
+				connection.negotiateProtocolVersion(new AbstractStateFunctor(failure) {
 					@Override
-					public void call(Exception e) {
-						if (e != null) {
-							log.fatal("unsupported protocol version!\n minimal version is: " + "\nmanager protocol is: " + connection.getProtocolVersion());
-							Dispatching.drop(connection, RemoteInstance.this);
-							fireRun(e);
-							return;
-						}
-
-						dispatch(new RunAt<Instance>() {
-							@Override
-							public void run() {
-								resolveAndFetch("/simulator", new Future<Path>() {
-									@Override
-									public void result(Path path, Exception e) {
-										if (e != null) {
-											log.fatal("failed to resolve simulator node");
-											fireRun(e);
-											return;
-										}
-										assert isActive();
-										simulator = path;
-										fireRun(null);
-										log.info("resolved simulator node");
-
-										EventParam param = getParam(simulator, "running_changed", EventParam.class);
-										assert param != null;
-										connection.subscribe(simulator.getTextual() + "/" + param.getId(), RemoteInstance.this, new LoggingSubscriptionCallback<Instance>(log, "server running state change", new EventCallback() {
-											@Override
-											public void call(List<File> files) {
-												dispatch(new RunAt<Instance>() {
-													@Override
-													public void run() {
-														updateSimulationRunning();
-													}
-												});
-											}
-										}));
-										new PeriodicTask<Instance>(RemoteInstance.this, 1000) {
-											@Override
-											public void run() {
-												updateSimulationRunning();
-												again();
-											}
-										};
-									}
-								});
-							}
-						});
+					public void call() {
+						onProtocolVersionNegotiated();
 					}
 				});
 			}
 		});
-
 	}
 
@@ -136,48 +105,4 @@
 	}
 
-	public void setRunning(final boolean running) {
-		assert isActive();
-		//simulator.call(simulator.getParam(running ? "start" : "stop", ProcedureParam.class), new LoggingStateCallback(log, (running ? "starting" : "stopping") + " server"));
-	}
-
-	protected final UnaryListenersSet<Boolean> simulationRunningListeners = new UnaryListenersSet<Boolean>();
-
-	protected void updateSimulationRunning() {
-		assert isActive();
-		/*
-		fetchValue(simulator, getParam(simulator, "running", Param.class), new StateFunctor() {
-			@Override
-			public void call(Exception e) {
-				if (e != null) {
-					log.fatal("failed to query simulator running status: " + e);
-					return;
-				}
-
-				invokeLater(new Runnable() {
-					@Override
-					public void run() {
-						boolean value = bindAccess(simulator).get("running", Boolean.class);
-						log.trace("server running: " + value);
-						simulationRunningListeners.call(value);
-					}
-				});
-
-			}
-		});
-		 */
-	}
-
-	public void addRunningStateListener(UnaryFunctor<Boolean, Boolean> listener) {
-		assert isActive();
-		simulationRunningListeners.add(listener);
-	}
-
-	// public void disconnect() {
-	//	assert isActive();
-	//	if (connection.isConnected()) {
-	//		Dispatching.stop(connection, this);
-	//	}
-	// }
-
 	public final ClientConnection getConnection() {
 		return connection;
@@ -185,5 +110,5 @@
 
 	@Override
-	public void fetchValue(final Path path, final Param param, final StateFunctor stateFunctor) {
+	public void fetchValue(final Path path, final ValueParam param, final StateFunctor stateFunctor) {
 		assert isActive();
 		assert param != null;
@@ -194,12 +119,12 @@
 				assert isActive();
 				if (!response.getOk()) {
-					stateFunctor.call(new Exception(response.getComment()));
+					stateFunctor.handle(new FramsticksException().msg("failed to fetch value").arg("comment", response.getComment()));
 					return;
 				}
 				try {
-					processFetchedValues(path, response.getFiles());
-					stateFunctor.call(null);
-				} catch (Exception ex) {
-					stateFunctor.call(ex);
+					InstanceUtils.processFetchedValues(path, response.getFiles());
+					stateFunctor.call();
+				} catch (FramsticksException ex) {
+					stateFunctor.handle(ex);
 				}
 			}
@@ -209,15 +134,15 @@
 	protected final Map<String, Set<Future<FramsClass>>> infoRequests = new HashMap<String, Set<Future<FramsClass>>>();
 
-	protected void finishInfoRequest(String id, FramsClass result, Exception e) {
+	protected void finishInfoRequest(String id, FramsClass result, FramsticksException e) {
 		assert isActive();
 		Set<Future<FramsClass>> futures = infoRequests.get(id);
 		infoRequests.remove(id);
 		for (Future<FramsClass> f : futures) {
-			f.result(result, e);
-		}
-	}
-
-	@Override
-	protected void fetchInfo(final Path path, final Future<FramsClass> future) {
+			Future.passOrHandle(f, result, e);
+		}
+	}
+
+	@Override
+	public void fetchInfo(final Path path, final Future<FramsClass> future) {
 
 		final String name = path.getTop().getParam().getContainedTypeName();
@@ -238,28 +163,25 @@
 			public void process(Response response) {
 				assert isActive();
-				if (!response.getOk()) {
-					finishInfoRequest(name, null, new Exception(response.getComment()));
-					return;
-				}
-
-				assert response.getFiles().size() == 1;
-				assert path.isTheSame(response.getFiles().get(0).getPath());
-				FramsClass framsClass;
 				try {
-					framsClass = processFetchedInfo(response.getFiles().get(0));
-				} catch (ConstructionException e) {
-					log.fatal("could not read class info");
-					finishInfoRequest(name, null, new Exception("could not read class info"));
-					return;
-				}
-
-				CompositeParam thisParam = path.getTop().getParam();
-				if (!thisParam.isMatchingContainedName(framsClass.getId())) {
-					String mismatch = "class name mismatch: param=" + thisParam.getContainedTypeName() + " differs from fetched=" + framsClass.getId();
-					log.error(mismatch);
-					finishInfoRequest(name, null, new Exception(mismatch));
-					return;
-				}
-				finishInfoRequest(name, framsClass, null);
+					if (!response.getOk()) {
+						throw new FramsticksException().msg("invalid response").arg("comment", response.getComment());
+					}
+					if (response.getFiles().size() != 1) {
+						throw new FramsticksException().msg("invalid number of files in response").arg("files", response.getFiles().size());
+					}
+					if (!path.isTheSame(response.getFiles().get(0).getPath())) {
+						throw new FramsticksException().msg("path mismatch").arg("returned path", response.getFiles().get(0).getPath());
+					}
+					FramsClass framsClass = InstanceUtils.processFetchedInfo(RemoteInstance.this, response.getFiles().get(0));
+
+					CompositeParam thisParam = path.getTop().getParam();
+					if (!thisParam.isMatchingContainedName(framsClass.getId())) {
+						throw new FramsticksException().msg("framsclass id mismatch").arg("request", thisParam.getContainedTypeName()).arg("fetched", framsClass.getId());
+					}
+
+					finishInfoRequest(name, framsClass, null);
+				} catch (FramsticksException e) {
+					finishInfoRequest(name, null, e.arg("path", path));
+				}
 			}
 		});
@@ -276,15 +198,12 @@
 			public void process(Response response) {
 				assert isActive();
-				if (!response.getOk()) {
-					stateFunctor.call(new Exception(response.getComment()));
-					return;
-				}
 				try {
-					processFetchedValues(path, response.getFiles());
-					stateFunctor.call(null);
-				} catch (Exception ex) {
-					log.error("an exception occurred while loading: " + ex);
-					ex.printStackTrace();
-					stateFunctor.call(ex);
+					if (!response.getOk()) {
+						throw new FramsticksException().msg("failed to fetch values").arg("comment", response.getComment());
+					}
+					InstanceUtils.processFetchedValues(path, response.getFiles());
+					stateFunctor.call();
+				} catch (FramsticksException e) {
+					stateFunctor.handle(e);
 				}
 			}
@@ -294,35 +213,5 @@
 	@Override
 	public void resolve(final Path path, final Future<Path> future) {
-		assert isActive();
-		if (path.getTop().getObject() != null) {
-			if (getInfoFromCache(path) != null) {
-				future.result(path, null);
-				return;
-			}
-			findInfo(path, new Future<FramsClass>() {
-				@Override
-				public void result(FramsClass result, Exception e) {
-					if (e != null) {
-						future.result(null, e);
-						return;
-					}
-					future.result(path, null);
-				}
-			});
-			return;
-		}
-		findInfo(path, new Future<FramsClass>() {
-			@Override
-			public void result(FramsClass result, Exception e) {
-				assert isActive();
-				if (e != null) {
-					future.result(null, e);
-					return;
-				}
-				assert path.getTop().getParam().isMatchingContainedName(result.getId());
-				Path p = (path.getTop().getParam().getContainedTypeName() != null ? path : path.tryFindResolution());
-				future.result(createIfNeeded(p), null);
-			}
-		});
+		InstanceUtils.resolve(path, future);
 	}
 
@@ -330,5 +219,5 @@
 	protected void tryRegisterOnChangeEvents(final Path path) {
 		assert isActive();
-		AccessInterface access = bindAccess(path);
+		AccessInterface access = InstanceUtils.bindAccess(path);
 		if (!(access instanceof ListAccess)) {
 			return;
@@ -396,22 +285,23 @@
 	}
 
+	protected Future<Path> futureListChanger(final ListChange listChange, final String path) {
+		return new Future<Path>(Logging.logger(log, "failed to " + listChange, path)) {
+			@Override
+			protected void result(Path result) {
+				log.debug(listChange + ": " + result);
+				fireListChange(result, listChange);
+			}
+		};
+	}
+
 	protected void reactToChange(final Path path, final ListChange listChange) {
 		assert isActive();
 		log.debug("reacting to change " + listChange + " in " + path);
-		AccessInterface access = bindAccess(path);
+		AccessInterface access = InstanceUtils.bindAccess(path);
 		assert access != null;
 
 		if ((listChange.getAction() == ListChange.Action.Modify) && (listChange.getPosition() == -1)) {
 			final String p = path.getTextual();
-			resolveAndFetch(p, new Future<Path>() {
-				@Override
-				public void result(Path result, Exception e) {
-					if (e != null) {
-						log.error("failed to modify " + p + ": " + e);
-						return;
-					}
-					fireListChange(path, listChange);
-				}
-			});
+			InstanceUtils.resolveAndFetch(this, p, futureListChanger(listChange, p));
 			return;
 		}
@@ -420,54 +310,31 @@
 		assert childParam != null;
 		switch (listChange.getAction()) {
-		case Add: {
-			final String p = path.getTextual() + "/" + childParam.getId();
-			resolveAndFetch(p, new Future<Path>() {
-				@Override
-				public void result(Path result, Exception e) {
-					if (e != null) {
-						log.error("failed to add " + p + ": " + e);
-						return;
-					}
-					log.debug("added: " + result);
-					fireListChange(path, listChange);
-				}
-			});
-			break;
-		}
-		case Remove: {
-			access.set(childParam, null);
-			fireListChange(path, listChange);
-			break;
-		}
-		case Modify: {
-			final String p = path.getTextual() + "/" + childParam.getId();
-			resolveAndFetch(p, new Future<Path>() {
-				@Override
-				public void result(Path result, Exception e) {
-					if (e != null) {
-						log.error("failed to modify " + p + ": " + e);
-						return;
-					}
-					fireListChange(path, listChange);
-				}
-			});
-			break;
-		}
-		}
-	}
-
-	//TODO ValueParam
-	@Override
-	public void storeValue(final Path path, final Param param, final Object value, final StateFunctor stateFunctor) {
+			case Add: {
+				final String p = path.getTextual() + "/" + childParam.getId();
+				InstanceUtils.resolveAndFetch(this, p, futureListChanger(listChange, p));
+				break;
+			}
+			case Remove: {
+				access.set(childParam, null);
+				fireListChange(path, listChange);
+				break;
+			}
+			case Modify: {
+				final String p = path.getTextual() + "/" + childParam.getId();
+				InstanceUtils.resolveAndFetch(this, p, futureListChanger(listChange, p));
+				break;
+			}
+		}
+	}
+
+	@Override
+	public void storeValue(final Path path, final ValueParam param, final Object value, StateFunctor stateFunctor) {
 		assert isActive();
 
 		log.trace("storing value " + param + " for " + path);
-		connection.send(new SetRequest().value(value.toString()).field(param.getId()).path(path.getTextual()), this, new StateCallback<Instance>() {
-			@Override
-			public void call(Exception e) {
-				if (e == null) {
-					bindAccess(path).set((ValueParam) param, value);
-				}
-				stateFunctor.call(e);
+		connection.send(new SetRequest().value(value.toString()).field(param.getId()).path(path.getTextual()), this, new StateCallback<Instance>(stateFunctor) {
+			@Override
+			protected void callImpl() {
+				InstanceUtils.bindAccess(path).set((ValueParam) param, value);
 			}
 		});
@@ -504,6 +371,47 @@
 
 	@Override
-	public void call(Path path, ProcedureParam param, Object[] arguments, StateFunctor stateFunctor) {
-		throw new UnimplementedException();
+	public void call(@Nonnull final Path path, @Nonnull final ProcedureParam procedure, @Nonnull Object[] arguments, final Future<Object> future) {
+		assert isActive();
+		assert path.isResolved();
+
+		//TODO validate arguments type using params
+		connection.send(new CallRequest().procedure(procedure.getId()).arguments(Arrays.asList(arguments)).path(path.getTextual()), this, new ResponseCallback<Instance>() {
+			@Override
+			public void process(Response response) {
+				assert isActive();
+				try {
+					if (!response.getOk()) {
+						throw new FramsticksException().msg("failed to call procedure").arg("procedure", procedure).arg("comment", response.getComment());
+					}
+					// InstanceUtils.processFetchedValues(path, response.getFiles());
+					future.pass(null);
+				} catch (FramsticksException ex) {
+					future.handle(ex);
+				}
+			}
+		});
+
+	}
+
+	@Override
+	public Path create(Path path) {
+		assert isActive();
+		assert !path.isResolved();
+		Path resolved = path.tryFindResolution();
+		if (!resolved.isResolved()) {
+			log.debug("creating: " + path);
+			AccessInterface access = registry.prepareAccess(path.getTop().getParam());
+			assert access != null;
+			Object child = access.createAccessee();
+			assert child != null;
+			if (path.size() == 1) {
+				setRoot(new Node(getRoot().getParam(), child));
+			} else {
+				bindAccess(this, path.getUnder()).set(path.getTop().getParam(), child);
+			}
+			resolved = path.appendResolution(child);
+		}
+		tryRegisterOnChangeEvents(resolved);
+		return resolved;
 	}
 
Index: /java/main/src/main/java/com/framsticks/remote/SimulatorInstance.java
===================================================================
--- /java/main/src/main/java/com/framsticks/remote/SimulatorInstance.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/remote/SimulatorInstance.java	(revision 96)
@@ -0,0 +1,112 @@
+package com.framsticks.remote;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import static com.framsticks.core.InstanceUtils.*;
+import com.framsticks.communication.EventCallback;
+import com.framsticks.communication.File;
+import com.framsticks.communication.util.LoggingSubscriptionCallback;
+import com.framsticks.core.Instance;
+import com.framsticks.core.InstanceUtils;
+import com.framsticks.core.Path;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.types.EventParam;
+import com.framsticks.util.Logging;
+import com.framsticks.util.PeriodicTask;
+import com.framsticks.util.UnaryFunctor;
+import com.framsticks.util.UnaryListenersSet;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.RunAt;
+
+@FramsClassAnnotation
+public class SimulatorInstance extends RemoteInstance {
+
+	private final static Logger log = Logger.getLogger(SimulatorInstance.class);
+
+	protected Path simulator;
+
+	/**
+	 *
+	 */
+	public SimulatorInstance() {
+		super();
+	}
+
+	public void setRunning(final boolean running) {
+		assert isActive();
+		//simulator.call(simulator.getParam(running ? "start" : "stop", ProcedureParam.class), new LoggingStateCallback(log, (running ? "starting" : "stopping") + " server"));
+	}
+
+	protected final UnaryListenersSet<Boolean> simulationRunningListeners = new UnaryListenersSet<Boolean>();
+
+	protected void updateSimulationRunning() {
+		assert isActive();
+		/*
+		fetchValue(simulator, getParam(simulator, "running", Param.class), new StateFunctor() {
+			@Override
+			public void call(Exception e) {
+				if (e != null) {
+					log.fatal("failed to query simulator running status: " + e);
+					return;
+				}
+
+				invokeLater(new Runnable() {
+					@Override
+					public void run() {
+						boolean value = bindAccess(simulator).get("running", Boolean.class);
+						log.trace("server running: " + value);
+						simulationRunningListeners.call(value);
+					}
+				});
+
+			}
+		});
+		 */
+	}
+
+	public void addRunningStateListener(UnaryFunctor<Boolean, Boolean> listener) {
+		assert isActive();
+		simulationRunningListeners.add(listener);
+	}
+	protected void onProtocolVersionNegotiated() {
+		dispatch(new RunAt<Instance>() {
+			@Override
+			public void run() {
+				resolveAndFetch(SimulatorInstance.this, "/simulator", new Future<Path>(Logging.logger(log, "failed to resolve simulator node", SimulatorInstance.this)) {
+					@Override
+					protected void result(Path path) {
+						assert isActive();
+						simulator = path;
+						fireRun(null);
+						log.info("resolved simulator node");
+
+						EventParam param = InstanceUtils.getInfoFromCache(simulator).getParamEntry("running_changed", EventParam.class);
+
+						assert param != null;
+						connection.subscribe(simulator.getTextual() + "/" + param.getId(), SimulatorInstance.this, new LoggingSubscriptionCallback<Instance>(log, "server running state change", new EventCallback() {
+							@Override
+							public void call(List<File> files) {
+								dispatch(new RunAt<Instance>() {
+									@Override
+									public void run() {
+										updateSimulationRunning();
+									}
+								});
+							}
+						}));
+						new PeriodicTask<Instance>(SimulatorInstance.this, 1000) {
+							@Override
+							public void run() {
+								updateSimulationRunning();
+								again();
+							}
+						};
+					}
+				});
+			}
+		});
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/running/ExternalProcess.java
===================================================================
--- /java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 96)
@@ -14,5 +14,4 @@
 import org.apache.log4j.Logger;
 
-import com.framsticks.core.Entity;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -30,5 +29,5 @@
 
 @FramsClassAnnotation
-public class ExternalProcess extends AbstractJoinable implements JoinableParent, Entity {
+public class ExternalProcess extends AbstractJoinable implements JoinableParent {
 	private static final Logger log = Logger.getLogger(ExternalProcess.class);
 
Index: /java/main/src/main/java/com/framsticks/test/TestClass.java
===================================================================
--- /java/main/src/main/java/com/framsticks/test/TestClass.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/test/TestClass.java	(revision 96)
@@ -0,0 +1,56 @@
+package com.framsticks.test;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.params.types.ProcedureParam;
+
+@FramsClassAnnotation(order = {"name", "history", "appendHistory", "resetHistory"})
+public class TestClass {
+
+	protected String name = "test";
+	protected String history = "";
+
+	/**
+	 * @return the name
+	 */
+	@ParamAnnotation
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @param name the name to set
+	 */
+	@ParamAnnotation
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return the history
+	 */
+	@ParamAnnotation
+	public String getHistory() {
+		return history;
+	}
+
+	/**
+	 * @param history the history to set
+	 */
+	@ParamAnnotation
+	public void setHistory(String history) {
+		this.history = history;
+	}
+
+	@ParamAnnotation(paramType = ProcedureParam.class)
+	public int appendHistory(String line) {
+		history = history + line + "|";
+		return history.length();
+	}
+
+	@ParamAnnotation(paramType = ProcedureParam.class)
+	public void resetHistory() {
+		history = "";
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/util/AbstractStateFunctor.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/AbstractStateFunctor.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/util/AbstractStateFunctor.java	(revision 96)
@@ -0,0 +1,26 @@
+package com.framsticks.util;
+
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+
+public abstract class AbstractStateFunctor implements StateFunctor {
+
+	protected final ExceptionResultHandler handler;
+
+	public AbstractStateFunctor() {
+		this.handler = null;
+	}
+
+	public AbstractStateFunctor(ExceptionResultHandler handler) {
+		this.handler = handler;
+	}
+
+	@Override
+	public void handle(FramsticksException exception) {
+		if (handler != null) {
+			handler.handle(exception);
+			return;
+		}
+		throw exception;
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/util/FramsticksException.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/FramsticksException.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/FramsticksException.java	(revision 96)
@@ -35,9 +35,9 @@
 	}
 
-	@Override
-	public String getMessage() {
-		StringBuilder b = new StringBuilder();
+	public void getShortMessage(StringBuilder b) {
 		if (message != null) {
 			b.append(message);
+		} else {
+			b.append("?");
 		}
 		if (arguments != null) {
@@ -45,11 +45,29 @@
 				b.append(" ");
 			}
-			Delimeted d = new Delimeted(", ", "");
+			Delimeted<Pair<String, Object>> d = new Delimeted<>(", ", "");
 			d.append(arguments.iterator());
 
 			b.append("(").append(d.build()).append(")");
 		}
-		if (this.getCause() != null) {
-			b.append(" caused by: [").append(this.getCause().getMessage()).append("]");
+	}
+
+	public String getMsg() {
+		return message;
+	}
+
+	@Override
+	public String getMessage() {
+		StringBuilder b = new StringBuilder();
+		getShortMessage(b);
+		Throwable cause = this.getCause();
+		while (cause != null) {
+			b.append(" caused by: [").append(cause.getClass().getCanonicalName()).append(": ");
+			if (cause instanceof FramsticksException) {
+				((FramsticksException) cause).getShortMessage(b);
+			} else {
+				b.append(cause.getMessage());
+			}
+			b.append("]");
+			cause = cause.getCause();
 		}
 		return b.toString();
Index: /java/main/src/main/java/com/framsticks/util/Logging.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/Logging.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/Logging.java	(revision 96)
@@ -2,4 +2,6 @@
 
 import org.apache.log4j.Logger;
+
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 
 /**
@@ -17,3 +19,12 @@
 		return false;
 	}
+
+	public static ExceptionResultHandler logger(final Logger logger, final String action, final Object subject) {
+		return new ExceptionResultHandler() {
+			@Override
+			public void handle(FramsticksException e) {
+				Logging.log(logger, action, subject, e);
+			}
+		};
+	}
 }
Index: /java/main/src/main/java/com/framsticks/util/PeriodicTask.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/PeriodicTask.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/PeriodicTask.java	(revision 96)
@@ -21,5 +21,5 @@
 
 	public void again() {
-		dispatcher.dispatch(new Task<C>(System.currentTimeMillis() + period) {
+		dispatcher.dispatch(new Task<C>(period) {
 			@Override
 			public void run() {
Index: /java/main/src/main/java/com/framsticks/util/StateFunctor.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/StateFunctor.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/StateFunctor.java	(revision 96)
@@ -1,9 +1,11 @@
 package com.framsticks.util;
+
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 
 /**
  * @author Piotr Sniegowski
  */
-public interface StateFunctor {
+public interface StateFunctor extends ExceptionResultHandler {
 	//TODO RunAt
-	public void call(Exception e);
+	public void call();
 }
Index: /java/main/src/main/java/com/framsticks/util/UnsupportedOperationException.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/UnsupportedOperationException.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/UnsupportedOperationException.java	(revision 96)
@@ -4,5 +4,5 @@
  * @author Piotr Sniegowski
  */
-public class UnsupportedOperationException extends Exception {
+public class UnsupportedOperationException extends FramsticksException {
 
 	/**
Index: /java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java	(revision 96)
@@ -14,9 +14,7 @@
 import com.framsticks.util.FramsticksException;
 
-
-
 public abstract class AbstractJoinable implements Joinable {
+
 	private static final Logger log = Logger.getLogger(AbstractJoinable.class);
-
 
 	protected final Set<JoinableParent> owners = new HashSet<JoinableParent>();
@@ -25,5 +23,7 @@
 	protected static final Set<AbstractJoinable> joinablesRegistry = Collections.synchronizedSet(new HashSet<AbstractJoinable>());
 
-	JoinableState state = JoinableState.INITILIAZED;
+	protected JoinableState state = JoinableState.INITILIAZED;
+	protected JoinableParent parent;
+	protected Monitor monitor;
 
 	/**
@@ -53,17 +53,16 @@
 		this.state = state;
 
-		synchronized (this) {
-			log.debug(this + " is notifying " + joinableListeners.size() + " parents");
-
-			List<JoinableParent> parents = new LinkedList<>();
-			CollectionUtils.addAll(parents, joinableListeners.iterator());
-
-			for (JoinableParent p : parents) {
-				if (p != null) {
-					Dispatching.childChangedState(p, this, state);
-				}
-			}
-			this.notifyAll();
-		}
+		log.debug(this + " is notifying " + joinableListeners.size() + " parents");
+
+		List<JoinableParent> parents = new LinkedList<>();
+		CollectionUtils.addAll(parents, joinableListeners.iterator());
+
+		for (JoinableParent p : parents) {
+			if (p != null) {
+				Dispatching.childChangedState(p, this, state);
+			}
+		}
+		this.notifyAll();
+
 		report();
 
@@ -145,4 +144,6 @@
 		}
 		if (start) {
+			assert monitor == null;
+			monitor = owner.getMonitor();
 			return this.start();
 		}
@@ -185,4 +186,18 @@
 	}
 
+	protected boolean isRunning() {
+		return state.equals(JoinableState.RUNNING);
+	}
+
+	@Override
+	public String toString() {
+		return getName();
+	}
+
+	// @Override
+	public Monitor getMonitor() {
+		return monitor;
+	}
+
 
 }
Index: /java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 96)
@@ -3,4 +3,5 @@
 import org.apache.log4j.Logger;
 
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.StateFunctor;
 
@@ -28,5 +29,5 @@
 			@Override
 			public void run() {
-				stateFunctor.call(null);
+				stateFunctor.call();
 			}
 		});
@@ -170,5 +171,47 @@
 	}
 
-
+	public static class Waiter {
+		protected boolean done = false;
+
+		protected final double timeOut;
+
+		/**
+		 * @param timeOut
+		 */
+		public Waiter(double timeOut) {
+			this.timeOut = timeOut;
+		}
+
+		public synchronized void pass() {
+			done = true;
+			this.notify();
+		}
+
+		public synchronized void waitFor() {
+			long end = System.currentTimeMillis() + (int)(timeOut * 1000);
+			while ((!done) && System.currentTimeMillis() < end) {
+				try {
+					this.wait(end - System.currentTimeMillis());
+				} catch (InterruptedException e) {
+					break;
+				}
+			}
+			if (!done) {
+				throw new FramsticksException().msg("waiter timed out");
+			}
+		}
+	}
+
+
+	public static <C> void synchronize(Dispatcher<C> dispatcher, double seconds) {
+		final Waiter waiter = new Waiter(seconds);
+		dispatcher.dispatch(new RunAt<C>() {
+			@Override
+			public void run() {
+				waiter.pass();
+			}
+		});
+		waiter.waitFor();
+	}
 
 }
Index: /java/main/src/main/java/com/framsticks/util/dispatching/ExceptionHandler.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/ExceptionHandler.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/ExceptionHandler.java	(revision 96)
@@ -0,0 +1,6 @@
+package com.framsticks.util.dispatching;
+
+public interface ExceptionHandler {
+	public boolean handle(Dispatcher<?> dispatcher, Throwable throwable);
+
+}
Index: /java/main/src/main/java/com/framsticks/util/dispatching/ExceptionResultHandler.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/ExceptionResultHandler.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/ExceptionResultHandler.java	(revision 96)
@@ -0,0 +1,7 @@
+package com.framsticks.util.dispatching;
+
+import com.framsticks.util.FramsticksException;
+
+public interface ExceptionResultHandler {
+	public void handle(FramsticksException exception);
+}
Index: /java/main/src/main/java/com/framsticks/util/dispatching/Future.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/Future.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/Future.java	(revision 96)
@@ -1,8 +1,46 @@
 package com.framsticks.util.dispatching;
+
+import com.framsticks.util.FramsticksException;
 
 /**
  * @author Piotr Sniegowski
  */
-public interface Future <T> {
-    void result(T result, Exception e);
+public abstract class Future<T> implements ExceptionResultHandler {
+
+	protected final ExceptionResultHandler handler;
+
+	public Future(ExceptionResultHandler handler) {
+		this.handler = handler;
+	}
+
+	public Future() {
+		this.handler = null;
+	}
+
+	protected abstract void result(T result);
+
+	public final void pass(T result) {
+		try {
+			result(result);
+		} catch (FramsticksException e) {
+			handle(e);
+		}
+	}
+
+	public static <T> void passOrHandle(Future<T> future, T value, FramsticksException e) {
+		if (e != null) {
+			future.handle(e);
+		} else {
+			future.pass(value);
+		}
+	}
+
+	@Override
+	public void handle(FramsticksException exception) {
+		if (handler != null) {
+			handler.handle(exception);
+			return;
+		}
+		throw exception;
+	}
 }
Index: /java/main/src/main/java/com/framsticks/util/dispatching/Joinable.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/Joinable.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/Joinable.java	(revision 96)
@@ -5,4 +5,11 @@
 
 public interface Joinable {
+
+	/** The name of the joinable.
+	 *
+	 * It should never be empty, but it is not required to remain
+	 * constant during lifetime of the object.
+	 */
+	public String getName();
 
 	public boolean use(@Nonnull JoinableParent owner);
Index: /java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java	(revision 96)
@@ -2,11 +2,8 @@
 
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.Map;
 import java.util.Set;
 
-import com.framsticks.core.Entity;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -19,5 +16,4 @@
 
 	protected final Set<T> joinables = new HashSet<T>();
-	protected final Map<String, T> namedJoinables = new HashMap<>();
 
 	protected boolean finishIfOne;
@@ -34,22 +30,17 @@
 
 	@AutoAppendAnnotation
-	public void add(T joinable) {
-		assert isInState(JoinableState.INITILIAZED);
+	public synchronized void add(T joinable) {
+		if (this.state.ordinal() > JoinableState.RUNNING.ordinal()) {
+			throw new FramsticksException().msg("failed to add joinable - collection is passed running state").arg("joinable", joinable).arg("collection", this);
+		}
 
 		if (joinables.contains(joinable)) {
 			throw new FramsticksException().msg("joinable is already observed").arg("joinable", joinable).arg("in", this);
 		}
-		// if (observables.containsKey(observable.getName())) {
-		// 	throw new FramsticksException().msg("observable with given name already exists").arg("name", observable.getName()).arg("in", this);
-		// }
+		joinables.add(joinable);
 
-		if (joinable instanceof Entity) {
-			Entity e = (Entity) joinable;
-			if (!namedJoinables.containsKey(e.getName())) {
-				namedJoinables.put(e.getName(), joinable);
-			}
+		if (this.state.equals(JoinableState.RUNNING)) {
+			Dispatching.use(joinable, this);
 		}
-
-		joinables.add(joinable);
 	}
 
@@ -107,5 +98,4 @@
 	public void childChangedState(Joinable joinable, JoinableState state) {
 		proceedToState(getNextState());
-
 	}
 
@@ -129,10 +119,23 @@
 
 	public T get(String name) {
-		return namedJoinables.get(name);
+		for (T j : joinables) {
+			if (j.getName().equals(name)) {
+				return j;
+			}
+		}
+		return null;
 	}
 
+	public int size() {
+		return joinables.size();
+	}
 
-	public Map<String, T> getObservables() {
-		return Collections.unmodifiableMap(namedJoinables);
+	public boolean contains(T joinable) {
+		return joinables.contains(joinable);
+	}
+
+	@Override
+	public String getName() {
+		return observableName;
 	}
 
Index: /java/main/src/main/java/com/framsticks/util/dispatching/JoinableParent.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/JoinableParent.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/JoinableParent.java	(revision 96)
@@ -4,4 +4,5 @@
 
 	public void childChangedState(Joinable joinable, JoinableState state);
+	public Monitor getMonitor();
 
 }
Index: /java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java	(revision 96)
@@ -2,6 +2,6 @@
 
 import org.apache.log4j.Logger;
-// import edu.umd.cs.findbugs.annotations.SuppressWarnings;
 import com.framsticks.util.dispatching.Dispatching;
+import java.lang.Thread;
 
 public class Monitor implements JoinableParent {
@@ -10,4 +10,5 @@
 
 	protected final Joinable joinable;
+	protected final Thread shutdownHook;
 
 	/**
@@ -16,4 +17,20 @@
 	public Monitor(Joinable joinable) {
 		this.joinable = joinable;
+
+		shutdownHook = new Thread(new Runnable() {
+			@Override
+			public void run() {
+				log.debug("running shutdown hook");
+				Monitor.this.drop().join();
+			}
+		});
+	}
+
+	public Monitor use() {
+		Runtime.getRuntime().addShutdownHook(shutdownHook);
+
+		log.debug(this + " is using");
+		Dispatching.use(joinable, this);
+		return this;
 	}
 
@@ -34,9 +51,4 @@
 	}
 
-	public Monitor use() {
-		log.debug(this + " is using");
-		Dispatching.use(joinable, this);
-		return this;
-	}
 
 	public Monitor drop() {
@@ -50,4 +62,11 @@
 		Dispatching.joinAbsolutely(joinable);
 		log.debug(this + " is joined");
+
+		try {
+			Runtime.getRuntime().removeShutdownHook(shutdownHook);
+		} catch (IllegalStateException e) {
+			/** In case IllegalStateException is caught, it means that JVM is in finalization stage */
+		}
+
 		return this;
 	}
@@ -67,3 +86,24 @@
 	}
 
+	@Override
+	public Monitor getMonitor() {
+		return this;
+	}
+
+	protected ExceptionHandler taskExceptionHandler;
+
+	/**
+	 * @return the taskExceptionHandler
+	 */
+	public ExceptionHandler getTaskExceptionHandler() {
+		return taskExceptionHandler;
+	}
+
+	/**
+	 * @param taskExceptionHandler the taskExceptionHandler to set
+	 */
+	public void setTaskExceptionHandler(ExceptionHandler taskExceptionHandler) {
+		this.taskExceptionHandler = taskExceptionHandler;
+	}
+
 }
Index: /java/main/src/main/java/com/framsticks/util/dispatching/Task.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/Task.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/Task.java	(revision 96)
@@ -13,5 +13,5 @@
 
 	public Task(long moment) {
-		this.moment = moment;
+		this.moment = System.currentTimeMillis() + moment;
 	}
 
Index: /java/main/src/main/java/com/framsticks/util/dispatching/Thread.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 96)
@@ -47,4 +47,6 @@
 	protected void routine() {
 		log.debug("starting thread " + this);
+		assert getMonitor() != null;
+		ExceptionHandler exceptionHandler = getMonitor().getTaskExceptionHandler();
 		while (!java.lang.Thread.interrupted()) {
 			Task<? extends C> task;
@@ -73,4 +75,9 @@
 				task.run();
 			} catch (Exception e) {
+				if (exceptionHandler != null) {
+					if (exceptionHandler.handle(this, e)) {
+						continue;
+					}
+				}
 				log.error("error in thread: ", e);
 			}
Index: /java/main/src/main/java/com/framsticks/util/dispatching/WrappedFuture.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/dispatching/WrappedFuture.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/util/dispatching/WrappedFuture.java	(revision 96)
@@ -0,0 +1,30 @@
+package com.framsticks.util.dispatching;
+
+public abstract class WrappedFuture<T> extends Future<T> {
+
+	public abstract T process(T result);
+
+	protected Future<T> future;
+
+	public WrappedFuture(Future<T> future) {
+		super(future);
+		this.future = future;
+	}
+
+	@Override
+	protected void result(T result) {
+		T processed;
+		processed = process(result);
+		if (future != null) {
+			future.pass(processed);
+		}
+	}
+
+	public Future<T> move() {
+		assert future != null;
+		Future<T> result = future;
+		future = null;
+		return result;
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/util/lang/Delimeted.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/lang/Delimeted.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/lang/Delimeted.java	(revision 96)
@@ -3,7 +3,7 @@
 import java.util.Iterator;
 
-import org.apache.commons.collections.Closure;
+// import org.apache.commons.collections.Closure;
 
-public class Delimeted implements Closure {
+public class Delimeted<T> {
 
 	protected final String delimeter;
@@ -19,5 +19,5 @@
 	}
 
-	public final Delimeted append(Object object) {
+	public final Delimeted<T> append(T object) {
 		if (builder != null) {
 			builder.append(delimeter);
@@ -29,5 +29,5 @@
 	}
 
-	public final Delimeted append(Iterator<?> i) {
+	public final Delimeted<T> append(Iterator<T> i) {
 		while (i.hasNext()) {
 			append(i.next());
@@ -41,7 +41,12 @@
 
 	@Override
-	public void execute(Object input) {
-		append(input);
+	public String toString() {
+		return build();
 	}
 
+	// @Override
+	// public void execute(Object input) {
+	// 	append(input);
+	// }
+
 }
Index: /java/main/src/main/java/com/framsticks/util/lang/Holder.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/lang/Holder.java	(revision 96)
+++ /java/main/src/main/java/com/framsticks/util/lang/Holder.java	(revision 96)
@@ -0,0 +1,35 @@
+package com.framsticks.util.lang;
+
+public class Holder<T> {
+
+	protected T value;
+
+
+	/**
+	 *
+	 */
+	public Holder() {
+	}
+
+	/**
+	 * @param value
+	 */
+	public Holder(T value) {
+		this.value = value;
+	}
+
+	/**
+	 * @return the value
+	 */
+	public T get() {
+		return value;
+	}
+
+	/**
+	 * @param value the value to set
+	 */
+	public void set(T value) {
+		this.value = value;
+	}
+
+}
Index: /java/main/src/main/java/com/framsticks/util/lang/Pair.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/lang/Pair.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/lang/Pair.java	(revision 96)
@@ -24,5 +24,4 @@
 		}
 		Pair<?, ?> p = (Pair<?, ?>) obj;
-		// return first == p.first && second.equals(se)
 		return first.equals(p.first) && second.equals(p.second);
 	}
@@ -33,3 +32,7 @@
 	}
 
+	public static <U1, U2> Pair<U1, U2> make(U1 first, U2 second) {
+		return new Pair<U1, U2>(first, second);
+	}
+
 }
Index: /java/main/src/main/java/com/framsticks/util/lang/Strings.java
===================================================================
--- /java/main/src/main/java/com/framsticks/util/lang/Strings.java	(revision 95)
+++ /java/main/src/main/java/com/framsticks/util/lang/Strings.java	(revision 96)
@@ -1,3 +1,5 @@
 package com.framsticks.util.lang;
+
+import com.framsticks.util.FramsticksException;
 
 /**
@@ -15,4 +17,10 @@
 	public static boolean notEmpty(String str) {
 		return str != null && !str.equals("");
+	}
+
+	public static void assureNotEmpty(String str) {
+		if (!notEmpty(str)) {
+			throw new FramsticksException().msg("string is empty");
+		}
 	}
 
@@ -35,9 +43,7 @@
 		int pos = string.indexOf(separator);
 		if (pos == -1) {
-			return new Pair<String, String>(string.substring(0,
-					string.length() - 1), second);
+			return new Pair<String, String>(string, second);
 		} else {
-			return new Pair<String, String>(string.substring(0, pos),
-					string.substring(pos + 1));
+			return new Pair<String, String>(string.substring(0, pos), string.substring(pos + 1));
 		}
 	}
Index: /java/main/src/main/resources/configs/framsticks.xml
===================================================================
--- /java/main/src/main/resources/configs/framsticks.xml	(revision 95)
+++ /java/main/src/main/resources/configs/framsticks.xml	(revision 96)
@@ -3,13 +3,15 @@
 	<import class="com.framsticks.gui.Browser" />
 	<import class="com.framsticks.remote.RemoteInstance" />
+	<import class="com.framsticks.remote.SimulatorInstance" />
 	<import class="com.framsticks.model.ModelPackage" />
 	<import class="com.framsticks.model.ModelBuilder" />
 	<import class="com.framsticks.model.f0.SchemaBuilder" />
 	<import class="com.framsticks.core.ObjectInstance" />
+	<import class="com.framsticks.hosting.Server" />
 	<import class="com.framsticks.test.TestClass" />
 	<Browser>
-		<RemoteInstance name="localhost:9009" address="localhost:9009">
+		<SimulatorInstance name="localhost:9009" address="localhost:9009">
 			<ModelPackage />
-		</RemoteInstance>
+		</SimulatorInstance>
 		<ObjectInstance name="model">
 			<ModelBuilder resource="/examples/f0_example.txt" />
@@ -18,7 +20,10 @@
 			<SchemaBuilder />
 		</ObjectInstance>
+		<RemoteInstance name="remote" address="localhost:9007" />
+	</Browser>
+	<Server name="server" port="9007">
 		<ObjectInstance name="test">
 			<TestClass />
 		</ObjectInstance>
-	</Browser>
+	</Server>
 </Framsticks>
Index: /java/main/src/main/resources/configs/log4j.properties
===================================================================
--- /java/main/src/main/resources/configs/log4j.properties	(revision 95)
+++ /java/main/src/main/resources/configs/log4j.properties	(revision 96)
@@ -29,7 +29,9 @@
 
 log4j.logger.com.framsticks=INFO
+# log4j.logger.com.framsticks.core.Framsticks=DEBUG
+# log4j.logger.com.framsticks.gui.Frame=DEBUG
 # log4j.logger.com.framsticks.core.ObjectInstance=DEBUG
 # log4j.logger.com.framsticks.core.Instance=DEBUG
-log4j.logger.com.framsticks.gui.controls.ProcedureControl=DEBUG
+# log4j.logger.com.framsticks.gui.controls.ProcedureControl=DEBUG
 # log4j.logger.com.framsticks.params.ReflectionAccess=TRACE
 # log4j.logger.com.framsticks.util.dispatching.Dispatching=DEBUG
Index: /java/main/src/test/java/com/framsticks/communication/ConnectionTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/communication/ConnectionTest.java	(revision 96)
+++ /java/main/src/test/java/com/framsticks/communication/ConnectionTest.java	(revision 96)
@@ -0,0 +1,15 @@
+package com.framsticks.communication;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.test.TestConfiguration;
+
+@Test
+public class ConnectionTest extends TestConfiguration {
+
+	@Test
+	public void patterns() {
+	}
+
+
+}
Index: /java/main/src/test/java/com/framsticks/communication/RequestTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/communication/RequestTest.java	(revision 96)
+++ /java/main/src/test/java/com/framsticks/communication/RequestTest.java	(revision 96)
@@ -0,0 +1,54 @@
+package com.framsticks.communication;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.framsticks.communication.queries.CallRequest;
+import com.framsticks.communication.queries.GetRequest;
+import com.framsticks.communication.queries.InfoRequest;
+import com.framsticks.communication.queries.SetRequest;
+import com.framsticks.communication.queries.UseRequest;
+import com.framsticks.communication.queries.VersionRequest;
+import com.framsticks.test.TestConfiguration;
+import com.framsticks.util.lang.Pair;
+
+import static org.fest.assertions.Assertions.*;
+
+@Test
+public class RequestTest extends TestConfiguration {
+
+	@Test
+	public void genericParsing() {
+		assertThat(Request.takeIdentifier("first second")).isEqualTo(Pair.make("first", "second"));
+		assertThat(Request.takeIdentifier(" first ")).isEqualTo(Pair.make("first", ""));
+
+		assertThat(Request.takeString(" \"a long comment\" second")).isEqualTo(Pair.make("a long comment", "second"));
+		assertThat(Request.takeString(" simple second")).isEqualTo(Pair.make("simple", "second"));
+
+		assertThat(Request.takeRequestId(true, " 2 simple second")).isEqualTo(Pair.make(2, "simple second"));
+	}
+
+	@Test(dataProvider = "requests", dependsOnMethods = "genericParsing")
+	public void parsingAndPrintingRequests(Class<? extends Request> requestClass, String line) {
+		Pair<CharSequence, CharSequence> pair = Request.takeIdentifier(line);
+		Request request = Request.parse(pair.first, pair.second);
+		assertThat(request).isInstanceOf(requestClass);
+		assertThat(request.stringRepresentation()).isEqualTo(line);
+	}
+
+	@DataProvider
+	public Object[][] requests() {
+		return new Object[][] {
+			{ CallRequest.class, "call /object function first second \"thi rd\""},
+			{ GetRequest.class, "get /test"},
+			{ GetRequest.class, "get /test one_field"},
+			{ GetRequest.class, "get /test first_field,second_field"},
+			{ SetRequest.class, "set /test field value"},
+			{ SetRequest.class, "set /test field \"value with spaces\""},
+			{ VersionRequest.class, "version 4"},
+			{ InfoRequest.class, "info /some/path"},
+			{ UseRequest.class, "use request_id"}
+		};
+	}
+
+}
Index: /java/main/src/test/java/com/framsticks/core/FramsticksTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/core/FramsticksTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/core/FramsticksTest.java	(revision 96)
@@ -20,6 +20,6 @@
 		Framsticks framsticks = Framsticks.loadConfiguration(stream);
 		assertThat(framsticks).isNotNull();
-		assertThat(framsticks.getObservables().size()).isEqualTo(1);
-		assertThat(framsticks.getObservables().get("browser")).isInstanceOf(Browser.class);
+		assertThat(framsticks.size()).isEqualTo(1);
+		assertThat(framsticks.get("browser")).isInstanceOf(Browser.class);
 	}
 
Index: /java/main/src/test/java/com/framsticks/core/ObjectInstanceTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/core/ObjectInstanceTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/core/ObjectInstanceTest.java	(revision 96)
@@ -19,4 +19,7 @@
 import com.framsticks.params.ReflectionAccess;
 import com.framsticks.params.types.FloatParam;
+
+import static com.framsticks.core.InstanceUtils.*;
+
 
 import static org.fest.assertions.Assertions.*;
@@ -48,5 +51,5 @@
 	public void startInstance() {
 		instance = new ObjectInstance();
-		instance.getRegistry().takeAllFrom(schema.getRegistry());
+		instance.takeAllFrom(schema.getRegistry());
 
 		instance.setRootObject(model);
@@ -62,20 +65,20 @@
 			})).isEqualTo("bla");
 
-		assertDispatch(instance, new RunAt<Instance>() {
+		instance.dispatch(new RunAt<Instance>() {
 			@Override
 			public void run() {
 				assertThat(instance.getRootObject(Model.class).getNeuroDefinitions().get(2).details).isEqualTo("G");
 
-				Path path = instance.getPath("/");
+				Path path = Path.to(instance, "/");
 				assertThat(path.isResolved());
-				AccessInterface access = instance.bindAccess(path);
+				AccessInterface access = InstanceUtils.bindAccess(path);
 				assertThat(access.get("se", Double.class)).isEqualTo(1.0);
 
-				assertThat(instance.bindAccess("/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getDef(Double.class)).isEqualTo(1.0);
-				assertThat(instance.bindAccess("/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getMax(Double.class)).isEqualTo(999.0);
-				assertThat(instance.bindAccess("/parts/2")).isInstanceOf(ReflectionAccess.class);
-				assertThat(instance.getPath("/neurodefs").getTopObject()).isInstanceOf(ArrayList.class);
-				assertThat(instance.getPath("/joints/1").getTopObject()).isInstanceOf(Joint.class);
-				assertThat(instance.bindAccess("/parts/2").get("i", String.class)).isEqualTo("bla");
+				assertThat(bindAccess(instance, "/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getDef(Double.class)).isEqualTo(1.0);
+				assertThat(bindAccess(instance, "/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getMax(Double.class)).isEqualTo(999.0);
+				assertThat(bindAccess(instance, "/parts/2")).isInstanceOf(ReflectionAccess.class);
+				assertThat(Path.to(instance, "/neurodefs").getTopObject()).isInstanceOf(ArrayList.class);
+				assertThat(Path.to(instance, "/joints/1").getTopObject()).isInstanceOf(Joint.class);
+				assertThat(bindAccess(instance, "/parts/2").get("i", String.class)).isEqualTo("bla");
 			}
 		});
Index: /java/main/src/test/java/com/framsticks/core/XmlBasedTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/core/XmlBasedTest.java	(revision 96)
+++ /java/main/src/test/java/com/framsticks/core/XmlBasedTest.java	(revision 96)
@@ -0,0 +1,31 @@
+package com.framsticks.core;
+
+import java.io.InputStream;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.core.Framsticks;
+import com.framsticks.test.MonitorBasedTest;
+import com.framsticks.util.dispatching.Joinable;
+
+// import static org.fest.assertions.Assertions.*;
+
+@Test
+public abstract class XmlBasedTest extends MonitorBasedTest {
+
+	protected Framsticks framsticks;
+
+	@Override
+	protected Joinable createSubject() {
+		framsticks = Framsticks.loadConfiguration(getConfigurationStream());
+		return framsticks;
+	}
+
+	protected InputStream getConfigurationStream() {
+		return XmlBasedTest.class.getResourceAsStream("/configs/" + getConfigurationName());
+	}
+
+	protected abstract String getConfigurationName();
+
+
+}
Index: /java/main/src/test/java/com/framsticks/dumping/StreamTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/dumping/StreamTest.java	(revision 96)
+++ /java/main/src/test/java/com/framsticks/dumping/StreamTest.java	(revision 96)
@@ -0,0 +1,36 @@
+package com.framsticks.dumping;
+
+public class StreamTest {
+
+	public void testLoad() {
+
+		// dispatch(new RunAt<Instance>() {
+
+		// 	@Override
+		// 	public void run() {
+		// 		assert isActive();
+
+		// 		try {
+		// 			LoadStream stream = new LoadStream(FileInstance.this.getPath("/"), new BufferedReader(new InputStreamReader(new FileInputStream(file), Encoding.getFramsticksCharset())), FileInstance.this, new Future<Path>() {
+		// 				@Override
+		// 				public void result(Path result, Exception e) {
+		// 					if (e != null) {
+		// 						log.error("failed to load file instance " + FileInstance.this + ": " + e);
+		// 						fireRun(e);
+		// 						return;
+		// 					}
+		// 					log.info("loaded file instance " + FileInstance.this);
+		// 					fireRun(null);
+		// 				}
+		// 			});
+		// 			stream.load();
+		// 		} catch (IOException e) {
+		// 			log.error("io failure: " + e);
+		// 			fireRun(e);
+		// 		}
+		// 	}
+
+		// });
+	}
+
+}
Index: /java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 96)
@@ -9,10 +9,8 @@
 import org.fest.swing.fixture.FrameFixture;
 import org.fest.swing.fixture.JTreeFixture;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import com.framsticks.test.TestConfiguration;
-import com.framsticks.util.dispatching.Monitor;
+import com.framsticks.test.MonitorBasedTest;
+import com.framsticks.util.dispatching.Joinable;
 
 import static org.fest.assertions.Assertions.assertThat;
@@ -22,9 +20,8 @@
 
 @Test
-public abstract class BrowserBaseTest extends TestConfiguration {
+public abstract class BrowserBaseTest extends MonitorBasedTest {
 
 	private static final Logger log = Logger.getLogger(BrowserTest.class);
 
-	protected Monitor monitor;
 	protected Browser browser;
 	protected static Robot robot;
@@ -39,13 +36,11 @@
 	}
 
-	@BeforeClass(timeOut = 5000)
-	public void setUp() {
+	@Override
+	protected Joinable createSubject() {
+		configureBrowser();
+		return browser;
+	}
 
-		configureBrowser();
-
-		monitor = new Monitor(browser);
-
-		monitor.use();
-
+	protected void setUpAfterUse() {
 		frame = new FrameFixture(robot,
 				GuiActionRunner.execute(new GuiQuery<JFrame>() {
@@ -57,6 +52,8 @@
 
 		tree = frame.tree("tree");
+
 		log.debug("frame fixture done");
 	}
+
 
 	protected abstract void configureBrowser();
@@ -71,8 +68,3 @@
 	}
 
-	@AfterClass(timeOut = 5000)
-	public void tearDown() {
-		monitor.drop().join();
-	}
-
 }
Index: /java/main/src/test/java/com/framsticks/gui/BrowserTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 96)
@@ -10,5 +10,5 @@
 
 import com.framsticks.model.ModelPackage;
-import com.framsticks.remote.RemoteInstance;
+import com.framsticks.remote.SimulatorInstance;
 
 public class BrowserTest extends BrowserBaseTest {
@@ -16,5 +16,5 @@
 	private static final Logger log = Logger.getLogger(BrowserTest.class);
 
-	RemoteInstance localhost;
+	SimulatorInstance localhost;
 
 	@Override
@@ -22,5 +22,5 @@
 		browser = new Browser();
 
-		localhost = new RemoteInstance();
+		localhost = new SimulatorInstance();
 		localhost.setName("localhost");
 		localhost.setAddress("localhost:9009");
Index: /java/main/src/test/java/com/framsticks/gui/ObjectInstanceBrowserTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/gui/ObjectInstanceBrowserTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/gui/ObjectInstanceBrowserTest.java	(revision 96)
@@ -11,4 +11,6 @@
 import com.framsticks.parsers.XmlLoader;
 import com.framsticks.util.dispatching.RunAt;
+
+import static com.framsticks.core.InstanceUtils.*;
 
 @Test
@@ -29,5 +31,5 @@
 	@Test(timeOut = 10000)
 	public void testShow() {
-		assertDispatch(instance, new RunAt<Instance>() {
+		instance.dispatch(new RunAt<Instance>() {
 			@Override
 			public void run() {
@@ -40,8 +42,8 @@
 		clickAndExpandPath("model/parts/2");
 
-		assertDispatch(instance, new RunAt<Instance>() {
+		instance.dispatch(new RunAt<Instance>() {
 			@Override
 			public void run() {
-				assertThat(instance.bindAccess("/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getMax(Double.class)).isEqualTo(999.0);
+				assertThat(bindAccess(instance, "/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getMax(Double.class)).isEqualTo(999.0);
 			}
 		});
Index: /java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 96)
@@ -16,4 +16,5 @@
 import com.framsticks.test.TestClass;
 import com.framsticks.util.dispatching.RunAt;
+import static com.framsticks.core.InstanceUtils.*;
 
 @Test
@@ -34,5 +35,5 @@
 	@Test(timeOut = 10000)
 	public void testShow() {
-		assertDispatch(instance, new RunAt<Instance>() {
+		instance.dispatch(new RunAt<Instance>() {
 			@Override
 			public void run() {
@@ -43,8 +44,8 @@
 		clickAndExpandPath("test");
 
-		assertDispatch(instance, new RunAt<Instance>() {
+		instance.dispatch(new RunAt<Instance>() {
 			@Override
 			public void run() {
-				assertThat(instance.bindAccess("/").getFramsClass().getParam("history")).isInstanceOf(StringParam.class);
+				assertThat(bindAccess(instance, "/").getFramsClass().getParam("history")).isInstanceOf(StringParam.class);
 			}
 		});
@@ -52,8 +53,8 @@
 		// monitor.useFor(4.0);
 
-		assertDispatch(instance, new RunAt<Instance>() {
+		instance.dispatch(new RunAt<Instance>() {
 			@Override
 			public void run() {
-				AccessInterface access = instance.bindAccess("/");
+				AccessInterface access = bindAccess(instance, "/");
 				assertThat(access).isInstanceOf(ReflectionAccess.class);
 				FramsClass framsClass = access.getFramsClass();
@@ -74,8 +75,8 @@
 		waitForIdle();
 
-		assertDispatch(instance, new RunAt<Instance>() {
+		instance.dispatch(new RunAt<Instance>() {
 			@Override
 			public void run() {
-				assertThat(instance.bindAccess("/").get("history", String.class)).isEqualTo("argument|");
+				assertThat(bindAccess(instance, "/").get("history", String.class)).isEqualTo("argument|");
 			}
 		});
@@ -84,8 +85,8 @@
 		waitForIdle();
 
-		assertDispatch(instance, new RunAt<Instance>() {
+		instance.dispatch(new RunAt<Instance>() {
 			@Override
 			public void run() {
-				assertThat(instance.bindAccess("/").get("history", String.class)).isEqualTo("");
+				assertThat(bindAccess(instance, "/").get("history", String.class)).isEqualTo("");
 			}
 		});
Index: /java/main/src/test/java/com/framsticks/hosting/ServerTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/hosting/ServerTest.java	(revision 96)
+++ /java/main/src/test/java/com/framsticks/hosting/ServerTest.java	(revision 96)
@@ -0,0 +1,156 @@
+package com.framsticks.hosting;
+
+// import org.apache.log4j.Logger;
+import org.testng.annotations.Test;
+
+import com.framsticks.core.ObjectInstance;
+import com.framsticks.core.Path;
+import com.framsticks.core.XmlBasedTest;
+import com.framsticks.remote.RemoteInstance;
+
+import com.framsticks.test.TestClass;
+import com.framsticks.core.Instance;
+import com.framsticks.params.FramsClass;
+import com.framsticks.util.AbstractStateFunctor;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.params.AccessInterface;
+import com.framsticks.params.PropertiesAccess;
+import com.framsticks.params.ValueParam;
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.util.dispatching.Dispatching.Waiter;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.RunAt;
+
+import static com.framsticks.core.InstanceUtils.*;
+
+import static org.fest.assertions.Assertions.*;
+
+@Test
+public class ServerTest extends XmlBasedTest {
+
+	protected RemoteInstance remote;
+	protected FramsClass remoteTestFramsClass;
+	protected Path remotePath;
+
+	protected Server server;
+	protected ObjectInstance hosted;
+	protected TestClass hostedObject;
+
+	@Override
+	protected String getConfigurationName() {
+		return "ServerTest.xml";
+	}
+
+	@Test
+	public void runServer() {
+		assertThat(framsticks.size()).isEqualTo(2);
+		assertThat(framsticks.get("test")).isInstanceOf(Server.class);
+		assertThat(framsticks.get("remote")).isInstanceOf(RemoteInstance.class);
+
+		server = (Server) framsticks.get("test");
+		remote = (RemoteInstance) framsticks.get("remote");
+		assertThat(server.getHosted()).isInstanceOf(ObjectInstance.class);
+		hosted = (ObjectInstance) server.getHosted();
+		assertThat(hosted.getRootObject()).isInstanceOf(TestClass.class);
+		hostedObject = hosted.getRootObject(TestClass.class);
+	}
+
+	@Test(dependsOnMethods = "runServer")
+	public void fetchInfo() {
+		remote.dispatch(new RunAt<Instance>() {
+			@Override
+			public void run() {
+				remote.fetchInfo(Path.to(remote, "/"), new Future<FramsClass>(failOnException()) {
+					@Override
+					protected void result(FramsClass result) {
+						remoteTestFramsClass = result;
+						assertThat(result.getId()).isEqualTo("TestClass");
+					}
+				});
+			}
+		});
+
+		Dispatching.synchronize(remote, 1.0);
+	}
+
+	@Test(dependsOnMethods = "fetchInfo")
+	public void resolveAndfetchRootObject() {
+		final Waiter waiter = produceWaiter(1.0);
+
+		remote.dispatch(new RunAt<Instance>() {
+			@Override
+			public void run() {
+				final Path path = Path.to(remote, "/");
+				assertThat(path.isResolved()).isFalse();
+
+				remote.resolve(path, new Future<Path>(failOnException()) {
+					@Override
+					protected void result(final Path result) {
+						assertThat(result.isResolved()).isTrue();
+						remotePath = result;
+						remote.fetchValues(result, new AbstractStateFunctor(failOnException()) {
+							@Override
+							public void call() {
+								AccessInterface access = bindAccess(result);
+								assertThat(access).isInstanceOf(PropertiesAccess.class);
+								assertThat(access.get("name", String.class)).isEqualTo("a test name");
+								waiter.pass();
+							}
+						});
+					}
+				});
+			}
+		});
+	}
+
+	@Test(dependsOnMethods = "resolveAndfetchRootObject")
+	public void setValueName() {
+		final Waiter waiter = produceWaiter(2.0);
+
+		storeValue(remotePath, remoteTestFramsClass.getParamEntry("name", ValueParam.class), "new name", new AbstractStateFunctor(failOnException()) {
+			@Override
+			public void call() {
+				/** And now check directly whether it was really set. */
+				hosted.dispatch(new RunAt<Instance>() {
+					@Override
+					public void run() {
+						assertThat(hostedObject.getName()).isEqualTo("new name");
+						waiter.pass();
+					}
+				});
+			}
+		});
+	}
+
+	@Test(dependsOnMethods = "setValueName")
+	public void callMethod() {
+		final Waiter firstWaiter = produceWaiter(2.0);
+		final Waiter waiter = produceWaiter(2.0);
+
+		call(remotePath, remoteTestFramsClass.getParamEntry("resetHistory", ProcedureParam.class), new Object[] {}, new Future<Object>(failOnException()) {
+			@Override
+			protected void result(Object result) {
+				firstWaiter.pass();
+			}
+		});
+
+		call(remotePath, remoteTestFramsClass.getParamEntry("appendHistory", ProcedureParam.class), new Object[] {"next word"}, new Future<Object>(failOnException()) {
+			@Override
+			protected void result(Object result) {
+				hosted.dispatch(new RunAt<Instance>() {
+					@Override
+					public void run() {
+						assertThat(hostedObject.getHistory()).isEqualTo("next word|");
+						waiter.pass();
+					}
+				});
+			}
+		});
+
+	}
+
+	@Test(dependsOnMethods = "callMethod")
+	public void endWait() {
+		monitor.useFor(1.0);
+	}
+}
Index: /java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 96)
@@ -1,4 +1,5 @@
 package com.framsticks.params;
 
+import java.util.Arrays;
 
 import org.testng.annotations.BeforeClass;
@@ -7,4 +8,5 @@
 import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.params.types.StringParam;
+import com.framsticks.parsers.Savers;
 import com.framsticks.test.TestClass;
 import com.framsticks.test.TestConfiguration;
@@ -17,5 +19,4 @@
 	ReflectionAccess access;
 	TestClass test;
-
 
 	@BeforeClass
@@ -36,4 +37,5 @@
 		assertThat(framsClass.getParam("appendHistory")).isInstanceOf(ProcedureParam.class);
 		assertThat(framsClass.getParam("resetHistory")).isInstanceOf(ProcedureParam.class);
+
 		ProcedureParam appendHistory = framsClass.getParamEntry("appendHistory", ProcedureParam.class);
 		assertThat(appendHistory.getArgumentsType().size()).isEqualTo(1);
@@ -42,4 +44,37 @@
 
 	@Test(dependsOnMethods = "checkProcedureParams")
+	public void print() {
+		assertThat(Savers.saveFramsClass(new ListSink(), framsClass).getOut()).isEqualTo(
+				Arrays.asList(
+					"class:",
+					"name:TestClass",
+					"id:TestClass",
+					"",
+					"prop:",
+					"id:name",
+					"name:Name",
+					"type:s",
+					"",
+					"prop:",
+					"id:history",
+					"name:History",
+					"type:s",
+					"",
+					"prop:",
+					"id:appendHistory",
+					"name:AppendHistory",
+					"type:p d(s arg0)",
+					"",
+					"prop:",
+					"id:resetHistory",
+					"name:ResetHistory",
+					"type:p()",
+					""
+				)
+			);
+	}
+
+
+	@Test(dependsOnMethods = "print")
 	public void callProcedures() {
 		access = new ReflectionAccess(TestClass.class, framsClass);
Index: /java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java	(revision 96)
@@ -23,4 +23,5 @@
 		assertThat(builderFramsClass.getName()).isEqualTo("prop");
 		assertThat(builderFramsClass.getId()).isEqualTo("prop");
+		assertThat(builderFramsClass.getParamEntry("flags", ValueParam.class).getDef(Object.class)).isEqualTo(new Integer(0));
 		assertThat(builderFramsClass.getParamEntry("id", Param.class)).isInstanceOf(StringParam.class);
 	}
Index: /java/main/src/test/java/com/framsticks/running/FramsServerTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/running/FramsServerTest.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/running/FramsServerTest.java	(revision 96)
@@ -3,36 +3,24 @@
 import org.testng.annotations.Test;
 
-import com.framsticks.core.Framsticks;
-import com.framsticks.test.TestConfiguration;
-import com.framsticks.util.dispatching.Monitor;
+import com.framsticks.core.XmlBasedTest;
 
 import static org.fest.assertions.Assertions.*;
 
 @Test
-public class FramsServerTest extends TestConfiguration {
+public class FramsServerTest extends XmlBasedTest {
+
+	@Override
+	protected String getConfigurationName() {
+		return "FramsServerTest.xml";
+	}
 
 	@Test(timeOut = 3000)
 	public void runServer() {
-		Framsticks framsticks = Framsticks.loadConfiguration(FramsServerTest.class.getResourceAsStream("/configs/FramsServerTest.xml"));
+		assertThat(framsticks.size()).isEqualTo(1);
+		assertThat(framsticks.get("frams")).isInstanceOf(FramsServer.class);
 
-		assertThat(framsticks.getObservables().size()).isEqualTo(1);
-		assertThat(framsticks.getObservables().get("frams")).isInstanceOf(FramsServer.class);
-		// assertThat(framsticks.getObservables().get("remote")).isInstanceOf(RemoteInstance.class);
-
-		new Monitor(framsticks).use().useFor(1.0).drop().join();
-
-		// monitor.use();
-
-		// Dispatching.sleep(1000);
-
-		// // monitor.waitFor();
-		// monitor.drop();
-		// monitor.join();
-
-		// framsticks.start();
-
-		// framsticks.waitForObservables();
-
+		monitor.useFor(1.0);
 	}
 
+
 }
Index: /java/main/src/test/java/com/framsticks/test/MonitorBasedTest.java
===================================================================
--- /java/main/src/test/java/com/framsticks/test/MonitorBasedTest.java	(revision 96)
+++ /java/main/src/test/java/com/framsticks/test/MonitorBasedTest.java	(revision 96)
@@ -0,0 +1,36 @@
+package com.framsticks.test;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.Monitor;
+
+@Test
+public abstract class MonitorBasedTest extends TestConfiguration {
+
+	protected Monitor monitor;
+	protected Joinable subject;
+
+	protected abstract Joinable createSubject();
+
+	@BeforeClass(timeOut = 2000)
+	public void setUp() {
+		subject = createSubject();
+
+		monitor = new Monitor(subject);
+		monitor.setTaskExceptionHandler(createExceptionHandler());
+		monitor.use();
+
+		setUpAfterUse();
+	}
+
+	protected void setUpAfterUse() {
+	}
+
+	@AfterClass(timeOut = 3000)
+	public void tearDown() {
+		monitor.drop().join();
+	}
+}
Index: va/main/src/test/java/com/framsticks/test/TestClass.java
===================================================================
--- /java/main/src/test/java/com/framsticks/test/TestClass.java	(revision 95)
+++ 	(revision )
@@ -1,56 +1,0 @@
-package com.framsticks.test;
-
-import com.framsticks.params.annotations.FramsClassAnnotation;
-import com.framsticks.params.annotations.ParamAnnotation;
-import com.framsticks.params.types.ProcedureParam;
-
-@FramsClassAnnotation(order = {"name", "history", "appendHistory", "resetHistory"})
-public class TestClass {
-
-	protected String name = "test";
-	protected String history = "";
-
-	/**
-	 * @return the name
-	 */
-	@ParamAnnotation
-	public String getName() {
-		return name;
-	}
-
-	/**
-	 * @param name the name to set
-	 */
-	@ParamAnnotation
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	/**
-	 * @return the history
-	 */
-	@ParamAnnotation
-	public String getHistory() {
-		return history;
-	}
-
-	/**
-	 * @param history the history to set
-	 */
-	@ParamAnnotation
-	public void setHistory(String history) {
-		this.history = history;
-	}
-
-	@ParamAnnotation(paramType = ProcedureParam.class)
-	public int appendHistory(String line) {
-		history = history + line + "|";
-		return history.length();
-	}
-
-	@ParamAnnotation(paramType = ProcedureParam.class)
-	public void resetHistory() {
-		history = "";
-	}
-
-}
Index: /java/main/src/test/java/com/framsticks/test/TestConfiguration.java
===================================================================
--- /java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 95)
+++ /java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 96)
@@ -1,6 +1,8 @@
 package com.framsticks.test;
 
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.log4j.Logger;
@@ -8,6 +10,12 @@
 import org.testng.annotations.*;
 
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.dispatching.Dispatcher;
-import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Dispatching.Waiter;
+import com.framsticks.util.dispatching.ExceptionHandler;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+
+import static org.fest.assertions.Assertions.*;
 
 public class TestConfiguration {
@@ -21,70 +29,71 @@
 	}
 
-	private final List<AsyncAssert<?>> asyncAssertions = new LinkedList<AsyncAssert<?>>();
+	private final List<AssertionError> asyncAssertions = new LinkedList<>();
 
-	public class AsyncAssert<C> extends RunAt<C> {
-		final RunAt<? extends C> runnable;
-		boolean done = false;
-		AssertionError assertion;
+	public ExceptionHandler createExceptionHandler() {
+		return new ExceptionHandler() {
+			@Override
+			public boolean handle(Dispatcher<?> dispatcher, Throwable throwable) {
+				AssertionError ae;
+				if (AssertionError.class.isInstance(throwable)) {
+					ae = AssertionError.class.cast(throwable);
+				} else {
+					ae = new AssertionError();
+					ae.initCause(throwable);
+				}
+				synchronized (asyncAssertions) {
+					asyncAssertions.add(ae);
+				}
+				return true;
+			}
+		};
+	}
 
-		/**
-		 * @param runnable
-		 */
-		public AsyncAssert(RunAt<? extends C> runnable) {
-			this.runnable = runnable;
-		}
-
-		@Override
-		public void run() {
+	@AfterMethod
+	public void waitForWaiters() {
+		for (Waiter w : waiters) {
 			try {
-				runnable.run();
-			} catch (AssertionError e) {
-				assertion = e;
-			}
-			synchronized (this) {
-				done = true;
-				this.notifyAll();
+				w.waitFor();
+			} catch (FramsticksException e) {
+				AssertionError ae = new AssertionError();
+				ae.initCause(e);
+				asyncAssertions.add(ae);
 			}
 		}
 	}
 
-	public <C> void assertDispatch(Dispatcher<C> dispatcher, RunAt<? extends C> runnable) {
-		AsyncAssert<C> assertion = new AsyncAssert<C>(runnable);
+	@AfterMethod(timeOut = 1000, dependsOnMethods = "waitForWaiters")
+	public void processAsyncAssertions() {
 		synchronized (asyncAssertions) {
-			asyncAssertions.add(assertion);
-		}
-		dispatcher.dispatch(assertion);
-	}
-
-	@BeforeMethod
-	public void clearAsyncAsserts() {
-		synchronized (asyncAssertions) {
-			asyncAssertions.clear();
+			if (asyncAssertions.isEmpty()) {
+				return;
+			}
+			AssertionError a = asyncAssertions.get(0);
+			asyncAssertions.remove(0);
+			throw a;
 		}
 	}
 
-	@AfterMethod(timeOut = 5000)
-	public void waitForAsyncAsserts() {
-		while (true) {
-			AsyncAssert<?> assertion;
-			synchronized (asyncAssertions) {
-				if (asyncAssertions.isEmpty()) {
-					return;
-				}
-				assertion = asyncAssertions.get(0);
-				asyncAssertions.remove(0);
+	final Set<Waiter> waiters = new HashSet<>();
+
+	@BeforeMethod
+	public void clearWaiters() {
+		waiters.clear();
+	}
+
+	protected Dispatching.Waiter produceWaiter(double timeOut) {
+		Waiter waiter = new Waiter(timeOut);
+		waiters.add(waiter);
+		return waiter;
+	}
+
+	public static ExceptionResultHandler failOnException() {
+		return new ExceptionResultHandler() {
+			@Override
+			public void handle(FramsticksException e) {
+				assertThat(e).isNull();
 			}
-			synchronized (assertion) {
-				while (!assertion.done) {
-					try {
-						assertion.wait();
-					} catch (InterruptedException ignored) {
-					}
-				}
-				if (assertion.assertion != null) {
-					throw assertion.assertion;
-				}
-			}
-		}
+		};
+
 	}
 }
Index: /java/main/src/test/resources/configs/ServerTest.xml
===================================================================
--- /java/main/src/test/resources/configs/ServerTest.xml	(revision 96)
+++ /java/main/src/test/resources/configs/ServerTest.xml	(revision 96)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Framsticks>
+	<import class="com.framsticks.hosting.Server" />
+	<import class="com.framsticks.remote.RemoteInstance" />
+	<import class="com.framsticks.core.ObjectInstance" />
+	<import class="com.framsticks.test.TestClass" />
+	<import class="com.framsticks.running.LoggingOutputListener" />
+	<Server name="server" port="9007">
+		<ObjectInstance name="test">
+			<TestClass name="a test name" />
+		</ObjectInstance>
+	</Server>
+	<RemoteInstance name="remote" address="localhost:9007" />
+</Framsticks>
Index: /java/main/src/test/resources/configs/test.xml
===================================================================
--- /java/main/src/test/resources/configs/test.xml	(revision 95)
+++ /java/main/src/test/resources/configs/test.xml	(revision 96)
@@ -2,7 +2,7 @@
 <Framsticks>
 	<import class="com.framsticks.gui.Browser" />
-	<import class="com.framsticks.remote.RemoteInstance" />
+	<import class="com.framsticks.remote.SimulatorInstance" />
 	<Browser name="browser">
-		<RemoteInstance name="localhost:9009" address="localhost:9009" />
+		<SimulatorInstance name="localhost:9009" address="localhost:9009" />
 	</Browser>
 </Framsticks>
Index: /java/main/src/test/resources/log4j.properties
===================================================================
--- /java/main/src/test/resources/log4j.properties	(revision 95)
+++ /java/main/src/test/resources/log4j.properties	(revision 96)
@@ -27,4 +27,7 @@
 
 log4j.logger.com.framsticks=INFO
+# log4j.logger.com.framsticks.hosting.Server=DEBUG
+# log4j.logger.com.framsticks.communication.ServerConnection=TRACE
+# log4j.logger.com.framsticks.util.dispatching.AbstractJoinable=DEBUG
 # log4j.logger.com.framsticks.parsers.F0Writer=TRACE
 # log4j.logger.com.framsticks.core.ObjectInstance=DEBUG
