Index: java/main/src/main/java/com/framsticks/communication/Address.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/Address.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/communication/Address.java	(revision 97)
@@ -0,0 +1,57 @@
+package com.framsticks.communication;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.util.FramsticksException;
+
+@FramsClassAnnotation
+public class Address {
+
+	private final static Pattern pattern = Pattern.compile("^([^:]*)(:([0-9]+))?$");
+
+	protected final String hostName;
+	protected final int port;
+
+	/**
+	 * @param hostName
+	 * @param port
+	 */
+	public Address(String hostName, int port) {
+		this.hostName = hostName;
+		this.port = port;
+	}
+
+	public Address(String address) {
+		Matcher matcher = pattern.matcher(address);
+		if (!matcher.matches()) {
+			throw new FramsticksException().msg("invalid address").arg("address", address);
+		}
+		hostName = matcher.group(1);
+		port = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 9009;
+	}
+
+	@Override
+	public String toString() {
+		return hostName + ":" + port;
+	}
+
+	/**
+	 * @return the hostName
+	 */
+	@ParamAnnotation
+	public String getHostName() {
+		return hostName;
+	}
+
+	/**
+	 * @return the port
+	 */
+	@ParamAnnotation
+	public int getPort() {
+		return port;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/communication/ClientConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ClientConnection.java	(revision 96)
+++ 	(revision )
@@ -1,398 +1,0 @@
-package com.framsticks.communication;
-
-import com.framsticks.communication.queries.ApplicationRequest;
-import com.framsticks.communication.queries.RegistrationRequest;
-import com.framsticks.communication.queries.UseRequest;
-import com.framsticks.communication.queries.VersionRequest;
-import com.framsticks.communication.util.LoggingStateCallback;
-import com.framsticks.params.ListSource;
-import com.framsticks.util.*;
-import com.framsticks.util.dispatching.AtOnceDispatcher;
-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.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import com.framsticks.util.dispatching.RunAt;
-
-/**
- * @author Piotr Sniegowski
- */
-public class ClientConnection extends Connection {
-
-	private final static Logger log = Logger.getLogger(ClientConnection.class);
-
-	protected final Map<String, Subscription<?>> subscriptions = new HashMap<>();
-
-	/**
-	 * @param connectedFunctor the connectedFunctor to set
-	 */
-	public void setConnectedFunctor(StateFunctor connectedFunctor) {
-		this.connectedFunctor = connectedFunctor;
-	}
-
-	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;
-
-	private static abstract class InboundMessage {
-		protected String currentFilePath;
-		protected List<String> currentFileContent;
-		protected final List<File> files = new ArrayList<File>();
-
-		public abstract void eof();
-
-		protected void initCurrentFile(String path) {
-			currentFileContent = new LinkedList<String>();
-			currentFilePath = path;
-		}
-
-		protected void finishCurrentFile() {
-			if (currentFileContent == null) {
-				return;
-			}
-			files.add(new File(currentFilePath, new ListSource(currentFileContent)));
-			currentFilePath = null;
-			currentFileContent = null;
-		}
-
-		public abstract void startFile(String path);
-
-		public final void addLine(String line) {
-			assert line != null;
-			assert currentFileContent != null;
-			currentFileContent.add(line);
-		}
-
-		public List<File> getFiles() {
-			return files;
-		}
-	}
-
-	private static class EventFire extends InboundMessage {
-		public final Subscription<?> subscription;
-
-		private EventFire(Subscription<?> subscription) {
-			this.subscription = subscription;
-		}
-
-		public void startFile(String path) {
-			assert path == null;
-			initCurrentFile(null);
-		}
-
-		@Override
-		public void eof() {
-			finishCurrentFile();
-
-			subscription.dispatchCall(getFiles());
-		}
-	}
-
-	private static class SentQuery<C> extends InboundMessage {
-		Request request;
-		ResponseCallback<? extends C> callback;
-		Dispatcher<C> dispatcher;
-
-		public void startFile(String path) {
-			finishCurrentFile();
-			if (!Strings.notEmpty(path)) {
-				assert request instanceof ApplicationRequest;
-				path = ((ApplicationRequest) request).getPath();
-			}
-			Strings.assureNotEmpty(path);
-			initCurrentFile(path);
-		}
-
-		public void eof() {
-			assert Strings.notEmpty(currentFilePath);
-			finishCurrentFile();
-			//no-operation
-		}
-
-		@Override
-		public String toString() {
-			return request.toString();
-		}
-
-		public void dispatchResponseProcess(final Response response) {
-			Dispatching.dispatchIfNotActive(dispatcher, new RunAt<C>() {
-				@Override
-				public void run() {
-					callback.process(response);
-				}
-			});
-		}
-	}
-
-	private Map<Integer, SentQuery<?>> queryMap = new HashMap<>();
-
-	protected final String hostName;
-	protected final int port;
-
-	private static Pattern addressPattern = Pattern.compile("^([^:]*)(:([0-9]+))?$");
-
-
-	private SentQuery<?> currentlySentQuery;
-
-	public <C extends Connection> void send(Request request, ResponseCallback<C> callback) {
-		//TODO RunAt
-		send(request, AtOnceDispatcher.getInstance(), callback);
-	}
-
-	public <C> void send(Request request, Dispatcher<C> dispatcher, ResponseCallback<? extends C> callback) {
-
-		if (getState().ordinal() > JoinableState.RUNNING.ordinal()) {
-			log.fatal("not connected");
-			return;
-		}
-
-		final SentQuery<C> sentQuery = new SentQuery<C>();
-		sentQuery.request = request;
-		sentQuery.callback = callback;
-		sentQuery.dispatcher = dispatcher;
-
-		senderThread.dispatch(new RunAt<Connection>() {
-			@Override
-			public void run() {
-				Integer id;
-				synchronized (ClientConnection.this) {
-
-					while (!(requestIdEnabled || currentlySentQuery == null)) {
-						try {
-							ClientConnection.this.wait();
-						} catch (InterruptedException ignored) {
-							break;
-						}
-					}
-					if (requestIdEnabled) {
-						queryMap.put(nextQueryId, sentQuery);
-						id = nextQueryId++;
-					} else {
-						currentlySentQuery = sentQuery;
-						id = null;
-					}
-				}
-				String command = sentQuery.request.getCommand();
-				StringBuilder message = new StringBuilder();
-				message.append(command);
-				if (id != null) {
-					message.append(" ").append(id);
-				}
-				message.append(" ");
-				sentQuery.request.construct(message);
-				String out = message.toString();
-
-				output.println(out);
-				output.flush();
-				log.debug("sending query: " + out);
-
-			}
-		});
-		/*
-		synchronized (this) {
-			log.debug("queueing query: " + query);
-			queryQueue.offer(sentQuery);
-			notifyAll();
-		}
-		 */
-	}
-
-	@Override
-	public String toString() {
-		return "client connection " + address;
-	}
-
-	public <C> void subscribe(final String path, final Dispatcher<C> dispatcher, final SubscriptionCallback<? extends C> callback) {
-		send(new RegistrationRequest().path(path), new ResponseCallback<Connection>() {
-			@Override
-			public void process(Response response) {
-				if (!response.getOk()) {
-					log.error("failed to register on event: " + path);
-					callback.subscribed(null);
-					return;
-				}
-				assert response.getFiles().isEmpty();
-				Subscription<C> subscription = new Subscription<C>(ClientConnection.this, path, response.getComment(), dispatcher);
-				log.debug("registered on event: " + subscription);
-				synchronized (subscriptions) {
-					subscriptions.put(subscription.getRegisteredPath(), subscription);
-				}
-				subscription.setEventCallback(callback.subscribed(subscription));
-				if (subscription.getEventCallback() == null) {
-					log.info("subscription for " + path + " aborted");
-					subscription.unsubscribe(new LoggingStateCallback<C>(log, "abort subscription"));
-				}
-			}
-		});
-	}
-
-	public void negotiateProtocolVersion(StateFunctor stateFunctor) {
-		protocolVersion = -1;
-		sendQueryVersion(1, stateFunctor);
-	}
-
-	public void sendQueryVersion(final int version, StateFunctor stateFunctor) {
-		send(new VersionRequest().version(version), new StateCallback<Connection>(stateFunctor) {
-			@Override
-			public void callImpl() {
-				protocolVersion = version;
-				if (version < 4) {
-					/** it is an implicit loop here*/
-					sendQueryVersion(version + 1, move());
-					return;
-				}
-				send(new UseRequest().feature("request_id"), new StateCallback<Connection>(move()) {
-					@Override
-					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;
-					}
-				});
-
-			}
-		});
-	}
-
-	private synchronized SentQuery<?> fetchQuery(Integer id, boolean remove) {
-		if (id == null) {
-			if (requestIdEnabled) {
-				return null;
-			}
-			SentQuery<?> result = currentlySentQuery;
-			if (remove) {
-				currentlySentQuery = null;
-				notifyAll();
-			}
-			return result;
-		}
-		if (queryMap.containsKey(id)) {
-			SentQuery<?> result = queryMap.get(id);
-			if (remove) {
-				queryMap.remove(id);
-			}
-			return result;
-		}
-		return null;
-	}
-
-	private int nextQueryId = 0;
-
-	protected void processMessage(InboundMessage inboundMessage) {
-		if (inboundMessage == null) {
-			log.error("failed to use any inbound message");
-			return;
-		}
-
-		String line;
-		while (!(line = getLine()).startsWith("eof")) {
-			// log.debug("line: " + line);
-			inboundMessage.addLine(line);
-		}
-		inboundMessage.eof();
-	}
-
-	protected void processEvent(String rest) {
-		Matcher matcher = Request.EVENT_PATTERN.matcher(rest);
-		if (!matcher.matches()) {
-			log.error("invalid event line: " + rest);
-			return;
-		}
-		Subscription<?> subscription = subscriptions.get(matcher.group(1));
-		if (subscription == null) {
-			log.error("non subscribed event: " + matcher.group(1));
-			return;
-		}
-		EventFire event = new EventFire(subscription);
-		event.startFile(null);
-		processMessage(event);
-	}
-
-	protected void processMessageStartingWith(String line) {
-		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 (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/ClientSideManagedConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java	(revision 97)
@@ -0,0 +1,398 @@
+package com.framsticks.communication;
+
+import com.framsticks.communication.queries.ApplicationRequest;
+import com.framsticks.communication.queries.ProtocolRequest;
+import com.framsticks.communication.queries.RegistrationRequest;
+import com.framsticks.communication.queries.UseRequest;
+import com.framsticks.communication.queries.VersionRequest;
+import com.framsticks.communication.util.LoggingStateCallback;
+import com.framsticks.params.ListSource;
+import com.framsticks.util.*;
+import com.framsticks.util.dispatching.AtOnceDispatcher;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.JoinableState;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
+
+import org.apache.log4j.Logger;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import com.framsticks.util.dispatching.RunAt;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class ClientSideManagedConnection extends ManagedConnection {
+
+	private final static Logger log = Logger.getLogger(ClientSideManagedConnection.class);
+
+	protected final Map<String, Subscription<?>> subscriptions = new HashMap<>();
+
+	private final List<Runnable> applicationRequestsBuffer = new LinkedList<>();
+	private boolean isHandshakeDone = false;
+
+	/**
+	 * @return the requestedVersion
+	 */
+	public int getRequestedVersion() {
+		return requestedVersion;
+	}
+
+	/**
+	 * @param requestedVersion the requestedVersion to set
+	 */
+	public void setRequestedVersion(int requestedVersion) {
+		this.requestedVersion = requestedVersion;
+	}
+
+	protected int requestedVersion = 4;
+
+	public ClientSideManagedConnection() {
+		setDescription("client connection");
+		protocolVersion = -1;
+	}
+
+
+	private static abstract class InboundMessage {
+		protected String currentFilePath;
+		protected List<String> currentFileContent;
+		protected final List<File> files = new ArrayList<File>();
+
+		public abstract void eof();
+
+		protected void initCurrentFile(String path) {
+			currentFileContent = new LinkedList<String>();
+			currentFilePath = path;
+		}
+
+		protected void finishCurrentFile() {
+			if (currentFileContent == null) {
+				return;
+			}
+			files.add(new File(currentFilePath, new ListSource(currentFileContent)));
+			currentFilePath = null;
+			currentFileContent = null;
+		}
+
+		public abstract void startFile(String path);
+
+		public final void addLine(String line) {
+			assert line != null;
+			assert currentFileContent != null;
+			currentFileContent.add(line);
+		}
+
+		public List<File> getFiles() {
+			return files;
+		}
+	}
+
+	private static class EventFire extends InboundMessage {
+		public final Subscription<?> subscription;
+
+		private EventFire(Subscription<?> subscription) {
+			this.subscription = subscription;
+		}
+
+		public void startFile(String path) {
+			assert path == null;
+			initCurrentFile(null);
+		}
+
+		@Override
+		public void eof() {
+			finishCurrentFile();
+
+			subscription.dispatchCall(getFiles());
+		}
+	}
+
+	private static class SentQuery<C> extends InboundMessage {
+		Request request;
+		ClientSideResponseFuture callback;
+		Dispatcher<C> dispatcher;
+
+		public void startFile(String path) {
+			finishCurrentFile();
+			if (!Strings.notEmpty(path)) {
+				assert request instanceof ApplicationRequest;
+				path = ((ApplicationRequest) request).getPath();
+			}
+			Strings.assureNotEmpty(path);
+			initCurrentFile(path);
+		}
+
+		public void eof() {
+			assert Strings.notEmpty(currentFilePath);
+			finishCurrentFile();
+			//no-operation
+		}
+
+		@Override
+		public String toString() {
+			return request.toString();
+		}
+
+		public void dispatchResponseProcess(final Response response) {
+			Dispatching.dispatchIfNotActive(dispatcher, new RunAt<C>(callback) {
+				@Override
+				protected void runAt() {
+					callback.pass(response);
+				}
+			});
+		}
+	}
+
+	private Map<Integer, SentQuery<?>> queryMap = new HashMap<>();
+
+	private SentQuery<?> currentlySentQuery;
+
+	public void send(ProtocolRequest request, ClientSideResponseFuture callback) {
+		//TODO RunAt
+		sendImplementation(request, AtOnceDispatcher.getInstance(), callback);
+	}
+
+
+
+	public <C> void send(final ApplicationRequest request, final Dispatcher<C> dispatcher, final ClientSideResponseFuture callback) {
+		synchronized (applicationRequestsBuffer) {
+			if (!isHandshakeDone) {
+				applicationRequestsBuffer.add(new Runnable() {
+					@Override
+					public void run() {
+						sendImplementation(request, dispatcher, callback);
+					}
+				});
+				return;
+			}
+		}
+		sendImplementation(request, dispatcher, callback);
+	}
+
+	private <C> void sendImplementation(Request request, Dispatcher<C> dispatcher, ClientSideResponseFuture callback) {
+
+		if (getState().ordinal() > JoinableState.RUNNING.ordinal()) {
+			log.fatal("not connected");
+			return;
+		}
+
+		final SentQuery<C> sentQuery = new SentQuery<C>();
+		sentQuery.request = request;
+		sentQuery.callback = callback;
+		sentQuery.dispatcher = dispatcher;
+
+		senderThread.dispatch(new RunAt<Connection>(callback) {
+			@Override
+			protected void runAt() {
+				Integer id;
+				synchronized (ClientSideManagedConnection.this) {
+
+					while (!(requestIdEnabled || currentlySentQuery == null)) {
+						try {
+							ClientSideManagedConnection.this.wait();
+						} catch (InterruptedException ignored) {
+							break;
+						}
+					}
+					if (requestIdEnabled) {
+						queryMap.put(nextQueryId, sentQuery);
+						id = nextQueryId++;
+					} else {
+						currentlySentQuery = sentQuery;
+						id = null;
+					}
+				}
+				String command = sentQuery.request.getCommand();
+				StringBuilder message = new StringBuilder();
+				message.append(command);
+				if (id != null) {
+					message.append(" ").append(id);
+				}
+				message.append(" ");
+				sentQuery.request.construct(message);
+				String out = message.toString();
+
+				putLine(out);
+				flushOut();
+				log.debug("sending query: " + out);
+
+			}
+		});
+		/*
+		synchronized (this) {
+			log.debug("queueing query: " + query);
+			queryQueue.offer(sentQuery);
+			notifyAll();
+		}
+		 */
+	}
+
+	@Override
+	public String toString() {
+		return "client connection " + address;
+	}
+
+	public <C> void subscribe(final String path, final Dispatcher<C> dispatcher, final SubscriptionCallback<? extends C> callback) {
+		send(new RegistrationRequest().path(path), AtOnceDispatcher.getInstance(), new ClientSideResponseFuture(callback) {
+			@Override
+			protected void processOk(Response response) {
+				assert response.getFiles().isEmpty();
+				Subscription<C> subscription = new Subscription<C>(ClientSideManagedConnection.this, path, response.getComment(), dispatcher);
+				log.debug("registered on event: " + subscription);
+				synchronized (subscriptions) {
+					subscriptions.put(subscription.getRegisteredPath(), subscription);
+				}
+				subscription.setEventCallback(callback.subscribed(subscription));
+				if (subscription.getEventCallback() == null) {
+					log.info("subscription for " + path + " aborted");
+					subscription.unsubscribe(new LoggingStateCallback(log, "abort subscription"));
+				}
+			}
+		});
+	}
+
+	private void sendQueryVersion(final int version, final Future<Void> future) {
+		send(new VersionRequest().version(version), new ClientSideResponseFuture(future) {
+			@Override
+			protected void processOk(Response response) {
+				protocolVersion = version;
+				if (version < requestedVersion) {
+					/** it is an implicit loop here*/
+					sendQueryVersion(version + 1, future);
+					return;
+				}
+				send(new UseRequest().feature("request_id"), new ClientSideResponseFuture(future) {
+
+					@Override
+					protected void processOk(Response response) {
+						requestIdEnabled = true;
+						future.pass(null);
+					}
+				});
+
+			}
+		});
+	}
+
+	private synchronized SentQuery<?> fetchQuery(Integer id, boolean remove) {
+		if (id == null) {
+			if (requestIdEnabled) {
+				return null;
+			}
+			SentQuery<?> result = currentlySentQuery;
+			if (remove) {
+				currentlySentQuery = null;
+				notifyAll();
+			}
+			return result;
+		}
+		if (queryMap.containsKey(id)) {
+			SentQuery<?> result = queryMap.get(id);
+			if (remove) {
+				queryMap.remove(id);
+			}
+			return result;
+		}
+		return null;
+	}
+
+	private int nextQueryId = 0;
+
+	protected void processMessage(InboundMessage inboundMessage) {
+		if (inboundMessage == null) {
+			log.error("failed to use any inbound message");
+			return;
+		}
+
+		String line;
+		while (!(line = getLine()).startsWith("eof")) {
+			// log.debug("line: " + line);
+			inboundMessage.addLine(line);
+		}
+		inboundMessage.eof();
+	}
+
+	protected void processEvent(String rest) {
+		Matcher matcher = Request.EVENT_PATTERN.matcher(rest);
+		if (!matcher.matches()) {
+			log.error("invalid event line: " + rest);
+			return;
+		}
+		Subscription<?> subscription = subscriptions.get(matcher.group(1));
+		if (subscription == null) {
+			log.error("non subscribed event: " + matcher.group(1));
+			return;
+		}
+		EventFire event = new EventFire(subscription);
+		event.startFile(null);
+		processMessage(event);
+	}
+
+	protected void processMessageStartingWith(String line) {
+		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);
+		}
+	}
+
+	protected final ExceptionResultHandler closeOnFailure = new ExceptionResultHandler() {
+
+		@Override
+		public void handle(FramsticksException exception) {
+			interrupt();
+			// finish();
+		}
+	};
+
+	@Override
+	protected void receiverThreadRoutine() {
+		startClientConnection(this);
+
+		sendQueryVersion(1, new FutureHandler<Void>(closeOnFailure) {
+
+			@Override
+			protected void result(Void result) {
+				synchronized (applicationRequestsBuffer) {
+					isHandshakeDone = true;
+					for (Runnable r : applicationRequestsBuffer) {
+						r.run();
+					}
+					applicationRequestsBuffer.clear();
+				}
+			}
+		});
+
+		processInputBatchesUntilClosed();
+	}
+
+	protected void processNextInputBatch() {
+		processMessageStartingWith(getLine());
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/communication/ClientSideRawConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ClientSideRawConnection.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/communication/ClientSideRawConnection.java	(revision 97)
@@ -0,0 +1,37 @@
+package com.framsticks.communication;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.RunAt;
+
+@FramsClassAnnotation
+public class ClientSideRawConnection extends Connection {
+
+	public ClientSideRawConnection() {
+		setDescription("client raw connection");
+	}
+
+	@Override
+	protected void receiverThreadRoutine() {
+		startClientConnection(this);
+
+		processInputBatchesUntilClosed();
+	}
+
+	protected void processNextInputBatch() {
+		getLine();
+	}
+
+	public void send(final String line, ExceptionResultHandler handler) {
+
+		senderThread.dispatch(new RunAt<ClientSideRawConnection>(handler) {
+			@Override
+			protected void runAt() {
+				putLine(line);
+				flushOut();
+			}
+		});
+
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/communication/ClientSideResponseFuture.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ClientSideResponseFuture.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/communication/ClientSideResponseFuture.java	(revision 97)
@@ -0,0 +1,24 @@
+package com.framsticks.communication;
+
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.FutureHandler;
+
+public abstract class ClientSideResponseFuture extends FutureHandler<Response> {
+
+	public ClientSideResponseFuture(ExceptionResultHandler handler) {
+		super(handler);
+	}
+
+	protected abstract void processOk(Response response);
+
+	@Override
+	protected final void result(Response response) {
+		if (response.getOk()) {
+			processOk(response);
+		} else {
+			handle(new FramsticksException().msg("invalid response").arg("comment", response.getComment()));
+		}
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/communication/Connection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 97)
@@ -1,7 +1,12 @@
 package com.framsticks.communication;
 
+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.io.Encoding;
-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.BufferedReader;
@@ -12,4 +17,7 @@
 import java.net.Socket;
 import java.net.SocketTimeoutException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 
 import com.framsticks.util.dispatching.AbstractJoinable;
@@ -21,66 +29,61 @@
 import com.framsticks.util.dispatching.RunAt;
 import com.framsticks.util.dispatching.Thread;
-
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+
+@FramsClassAnnotation
 public abstract class Connection extends AbstractJoinable implements JoinableParent {
 
 	protected final static Logger log = Logger.getLogger(Connection.class);
 
-	protected PrintWriter output = null;
-	protected BufferedReader input = null;
+	private PrintWriter output = null;
+	private BufferedReader input = null;
 
 	protected Socket socket = null;
 
-	public boolean requestIdEnabled = false;
-
-	protected int protocolVersion = -1;
-
-	public String getAddress() {
-		return address;
-	}
-	protected final String address;
-	protected final String description;
+	protected Address address;
+	protected String description = "connection";
 
 	protected final Thread<Connection> senderThread = new Thread<>();
 	protected final Thread<Connection> receiverThread = new Thread<>();
 	protected final JoinableCollection<Thread<Connection>> threads = new JoinableCollection<>();
-
-	protected void setUpThreadNames(String name) {
-	}
+	protected final Set<ConnectionListener> listeners = new HashSet<>();
 
 	/**
 	 *
 	 */
-	public Connection(String address, String description) {
-		this.address = address;
-		this.description = description;
-		threads.setObservableName(address + " connection threads");
+	public Connection() {
 		threads.add(senderThread);
 		threads.add(receiverThread);
 
+	}
+
+	protected void updateNames() {
+		if (address == null) {
+			return;
+		}
 		senderThread.setName(description + " thread " + address + " sender");
 		receiverThread.setName(description + " thread " + address + " receiver");
+		threads.setObservableName(address + " connection threads");
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+		updateNames();
+	}
+
+	@AutoAppendAnnotation
+	public Connection setAddress(Address address) {
+		this.address = address;
+		updateNames();
+		return this;
+	}
+
+	@ParamAnnotation
+	public Connection setAddress(String address) {
+		return setAddress(new Address(address));
 	}
 
 	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);
 	}
 
@@ -105,5 +108,13 @@
 					++iterator;
 					bufferStart = iterator;
-					return lineBuffer.toString();
+					String line = lineBuffer.toString();
+
+					synchronized (listeners) {
+						for (ConnectionListener l : listeners) {
+							l.connectionIncomming(line);
+						}
+					}
+
+					return line;
 				}
 				final int length = readChars - bufferStart;
@@ -131,7 +142,33 @@
 	}
 
+	protected void putLine(String line) {
+		synchronized (listeners) {
+			for (ConnectionListener l : listeners) {
+				l.connectionOutgoing(line);
+			}
+		}
+		output.println(line);
+	}
+
+	protected void flushOut() {
+		output.flush();
+	}
+
+	protected abstract void processNextInputBatch();
+
+	protected final void processInputBatchesUntilClosed() {
+		while (isRunning() && isConnected()) {
+			try {
+				processNextInputBatch();
+			} catch (Exception e) {
+				log.log(isRunning() ? Level.ERROR : Level.DEBUG, "caught exception: ", e);
+				break;
+			}
+		}
+	}
+
 	protected abstract void receiverThreadRoutine();
 
-
+	// @SuppressWarnings("NN_NAKED_NOTIFY")
 	protected void setupStreams() {
 		try {
@@ -146,12 +183,4 @@
 	}
 
-	/**
-	 * Returns Query associated with query getId.
-	 *
-	 * @return Query associated with query getId.
-	 */
-	public int getProtocolVersion() {
-		return protocolVersion;
-	}
 
 
@@ -187,5 +216,5 @@
 	@Override
 	public String getName() {
-		return description + " " + address;
+		return address != null ? description + " " + address : description;
 	}
 
@@ -194,7 +223,7 @@
 		Dispatching.use(threads, this);
 
-		senderThread.dispatch(new RunAt<Connection>() {
+		senderThread.dispatch(new RunAt<Connection>(ThrowExceptionHandler.getInstance()) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				synchronized (Connection.this) {
 					while (state.equals(JoinableState.RUNNING) && output == null) {
@@ -205,8 +234,10 @@
 		});
 
-		receiverThread.dispatch(new RunAt<Connection>() {
+		receiverThread.dispatch(new RunAt<Connection>(ThrowExceptionHandler.getInstance()) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				receiverThreadRoutine();
+				interrupt();
+				finish();
 			}
 		});
@@ -215,5 +246,4 @@
 	@Override
 	protected void joinableInterrupt() {
-		protocolVersion = -1;
 		Dispatching.drop(threads, this);
 		finish();
@@ -226,3 +256,48 @@
 	}
 
+	protected static void startClientConnection(Connection connection) {
+		while (connection.isRunning() && !connection.isConnected()) {
+			log.debug("connecting to " + connection.address);
+			try {
+				connection.socket = new Socket(connection.getAddressObject().getHostName(), connection.getAddressObject().getPort());
+			} catch (IOException e) {
+				log.info(connection + " failed to connect (retrying): " + e);
+				Dispatching.sleep(0.5);
+			}
+		}
+
+		log.debug(connection + " connected");
+		try {
+			connection.socket.setSoTimeout(500);
+			connection.setupStreams();
+		} catch (Exception e) {
+			throw new FramsticksException().msg("failed to initialize socket").cause(e).arg("connection", connection);
+		}
+	}
+
+	/**
+	 * @return the address
+	 */
+	@ParamAnnotation
+	public String getAddress() {
+		return Strings.toStringNullProof(address, "?");
+	}
+
+	public Address getAddressObject() {
+		return address;
+	}
+
+
+	/**
+	 * @return the listeners
+	 */
+	public Collection<ConnectionListener> getListeners() {
+		return listeners;
+	}
+
+	public static <T extends Connection> T to(T connection, Address address) {
+		connection.setAddress(address);
+		return connection;
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/communication/ConnectionListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ConnectionListener.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/communication/ConnectionListener.java	(revision 97)
@@ -0,0 +1,8 @@
+package com.framsticks.communication;
+
+import com.framsticks.util.dispatching.Joinable;
+
+public interface ConnectionListener extends Joinable {
+	public void connectionOutgoing(String line);
+	public void connectionIncomming(String line);
+}
Index: java/main/src/main/java/com/framsticks/communication/ManagedConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ManagedConnection.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/communication/ManagedConnection.java	(revision 97)
@@ -0,0 +1,33 @@
+package com.framsticks.communication;
+
+import com.framsticks.util.lang.Pair;
+
+public abstract class ManagedConnection extends Connection {
+
+	public boolean requestIdEnabled = false;
+
+	protected int protocolVersion = -1;
+
+	public ManagedConnection() {
+	}
+
+	protected final Pair<Integer, CharSequence> takeRequestId(CharSequence line) {
+		return Request.takeRequestId(requestIdEnabled, line);
+	}
+
+	/**
+	 * Returns Query associated with query getId.
+	 *
+	 * @return Query associated with query getId.
+	 */
+	public int getProtocolVersion() {
+		return protocolVersion;
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		protocolVersion = -1;
+		super.joinableInterrupt();
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/communication/RequestHandler.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/RequestHandler.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/communication/RequestHandler.java	(revision 97)
@@ -7,4 +7,4 @@
  */
 public interface RequestHandler {
-	public void handle(ApplicationRequest request, ResponseCallback<?> responseCallback);
+	public void handle(ApplicationRequest request, ServerSideResponseFuture responseCallback);
 }
Index: java/main/src/main/java/com/framsticks/communication/ResponseCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ResponseCallback.java	(revision 96)
+++ 	(revision )
@@ -1,17 +1,0 @@
-package com.framsticks.communication;
-
-import com.framsticks.util.FramsticksException;
-import com.framsticks.util.dispatching.ExceptionResultHandler;
-
-/**
- * @author Piotr Sniegowski
- */
-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 96)
+++ 	(revision )
@@ -1,133 +1,0 @@
-package com.framsticks.communication;
-
-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;
-
-import java.net.Socket;
-import com.framsticks.util.dispatching.RunAt;
-
-/**
- * @author Piotr Sniegowski
- */
-public class ServerConnection extends Connection {
-
-	private final static Logger log = Logger.getLogger(ServerConnection.class);
-
-	RequestHandler requestHandler;
-
-	public ServerConnection(Socket socket, RequestHandler requestHandler) {
-		super(socket.getInetAddress().getHostAddress(), "server connection");
-		this.socket = socket;
-		this.requestHandler = requestHandler;
-		// socket.setSoTimeout(500);
-		setupStreams();
-	}
-
-
-	@Override
-	protected void receiverThreadRoutine() {
-		while (isRunning() && isConnected()) {
-			try {
-				processNextRequest();
-			} catch (Exception e) {
-				log.log((isRunning() ? Level.ERROR : Level.DEBUG), "caught exception: ", e);
-				break;
-			}
-		}
-		interrupt();
-		finish();
-	}
-
-	protected void handleRequest(Request request, ResponseCallback<?> responseCallback) {
-		if (request instanceof ApplicationRequest) {
-			requestHandler.handle((ApplicationRequest) request, responseCallback);
-			return;
-		}
-		if (request instanceof ProtocolRequest) {
-			if (request instanceof VersionRequest) {
-				responseCallback.process(new Response(true, null, null));
-				return;
-			}
-			if (request instanceof UseRequest) {
-				String feature = ((UseRequest)request).getFeature();
-				if (feature.equals("request_id")) {
-					requestIdEnabled = true;
-					responseCallback.process(new Response(true, null, null));
-					return;
-				}
-				responseCallback.process(new Response(false, "\"unknown feature: " + feature + "\"", null));
-				return;
-			}
-
-		}
-		log.error("unhandled request: " + request);
-		responseCallback.process(new Response(false, "unhandled", null));
-	}
-
-	protected final void respond(final Response response, final Integer id) {
-		senderThread.dispatch(new RunAt<Connection>() {
-			@Override
-			public void run() {
-				String outId = id != null ? " " + id : "";
-				if (response.getFiles() != null) {
-					for (File f : response.getFiles()) {
-						output.print("file" + outId/* + " " + f.getPath()*/ + "\n");
-						SourceInterface content = f.getContent();
-						String line;
-						while ((line = content.readLine()) != null) {
-							output.print(line);
-							output.print('\n');
-						}
-						output.print("eof\n");
-					}
-				}
-				output.print(response.getOk() ? "ok" : "error");
-				output.print(outId);
-				if (Strings.notEmpty(response.getComment())) {
-					output.print(" \"");
-					output.print(response.getComment());
-					output.print('"');
-				}
-				output.print('\n');
-				output.flush();
-			}
-		});
-
-	}
-
-	protected void processNextRequest() {
-		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;
-		}
-
-	}
-}
Index: java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java	(revision 97)
@@ -0,0 +1,130 @@
+package com.framsticks.communication;
+
+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.Logger;
+
+import java.net.Socket;
+import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class ServerSideManagedConnection extends ManagedConnection {
+
+	private final static Logger log = Logger.getLogger(ServerSideManagedConnection.class);
+
+	RequestHandler requestHandler;
+
+	public ServerSideManagedConnection(Socket socket, RequestHandler requestHandler) {
+		setAddress(new Address(socket.getInetAddress().getHostAddress(), socket.getPort()));
+		setDescription("server connection");
+		this.socket = socket;
+		this.requestHandler = requestHandler;
+		// socket.setSoTimeout(500);
+		setupStreams();
+	}
+
+
+	protected void processNextInputBatch() {
+		processNextRequest();
+	}
+
+	@Override
+	protected void receiverThreadRoutine() {
+
+		processInputBatchesUntilClosed();
+	}
+
+	protected void handleRequest(Request request, ServerSideResponseFuture responseCallback) {
+		if (request instanceof ApplicationRequest) {
+			requestHandler.handle((ApplicationRequest) request, responseCallback);
+			return;
+		}
+		if (request instanceof ProtocolRequest) {
+			if (request instanceof VersionRequest) {
+				responseCallback.pass(new Response(true, null, null));
+				return;
+			}
+			if (request instanceof UseRequest) {
+				String feature = ((UseRequest)request).getFeature();
+				if (feature.equals("request_id")) {
+					requestIdEnabled = true;
+					responseCallback.pass(new Response(true, null, null));
+					return;
+				}
+				responseCallback.pass(new Response(false, "unknown feature: " + feature, null));
+				return;
+			}
+
+		}
+		log.error("unhandled request: " + request);
+		responseCallback.pass(new Response(false, "unhandled", null));
+	}
+
+	protected final void respond(final Response response, final Integer id) {
+		//TODO TEH: pass it the hosted tree
+		senderThread.dispatch(new RunAt<Connection>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				String outId = id != null ? " " + id : "";
+				if (response.getFiles() != null) {
+					for (File f : response.getFiles()) {
+						putLine("file" + outId/* + " " + f.getPath()*/);
+						SourceInterface content = f.getContent();
+						String line;
+						while ((line = content.readLine()) != null) {
+							putLine(line);
+						}
+						putLine("eof");
+					}
+				}
+				StringBuilder statusLine = new StringBuilder();
+				statusLine.append(response.getOk() ? "ok" : "error").append(outId);
+				if (Strings.notEmpty(response.getComment())) {
+					statusLine.append(" \"").append(response.getComment()).append('"');
+				}
+				putLine(statusLine.toString());
+				flushOut();
+			}
+		});
+
+	}
+
+
+	protected void processNextRequest() {
+		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);
+			}
+
+			//TODO what to do here?
+			handleRequest(request, new ServerSideResponseFuture() {
+				@Override
+				protected void result(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;
+		}
+
+	}
+}
Index: java/main/src/main/java/com/framsticks/communication/ServerSideResponseFuture.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ServerSideResponseFuture.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/communication/ServerSideResponseFuture.java	(revision 97)
@@ -0,0 +1,16 @@
+package com.framsticks.communication;
+
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.Future;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class ServerSideResponseFuture extends Future<Response> {
+
+	@Override
+	public final void handle(FramsticksException e) {
+		result(new Response(false, e.getClass().getCanonicalName() + ": " + e.getMsg(), null));
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/communication/StateCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/StateCallback.java	(revision 96)
+++ 	(revision )
@@ -1,61 +1,0 @@
-package com.framsticks.communication;
-
-import com.framsticks.util.FramsticksException;
-import com.framsticks.util.StateFunctor;
-
-/**
- * @author Piotr Sniegowski
- */
-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) {
-		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 96)
+++ java/main/src/main/java/com/framsticks/communication/Subscription.java	(revision 97)
@@ -4,9 +4,10 @@
 
 import com.framsticks.communication.queries.RegistrationRequest;
+import com.framsticks.util.dispatching.AtOnceDispatcher;
 import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.dispatching.Dispatching;
 import com.framsticks.util.dispatching.RunAt;
-import com.framsticks.util.FramsticksException;
-import com.framsticks.util.StateFunctor;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+
 import org.apache.log4j.Logger;
 
@@ -19,5 +20,5 @@
 	private final static Logger log = Logger.getLogger(Subscription.class);
 
-	private final ClientConnection connection;
+	private final ClientSideManagedConnection connection;
 	private final String path;
 	private final String registeredPath;
@@ -26,5 +27,5 @@
 	private EventCallback eventCallback;
 
-	public Subscription(ClientConnection connection, String path, String registeredPath, Dispatcher<C> dispatcher) {
+	public Subscription(ClientSideManagedConnection connection, String path, String registeredPath, Dispatcher<C> dispatcher) {
 		this.connection = connection;
 		this.path = path;
@@ -46,17 +47,13 @@
 	}
 
-	public void unsubscribe(final StateFunctor stateFunctor) {
+	public void unsubscribe(final ClientSideResponseFuture future) {
 		//@todo remove that /cli/ prefix, when registeredPath will be a fully qualified path
-		connection.send(new RegistrationRequest().register(false).path(registeredPath), new ResponseCallback<Connection>() {
+		connection.send(new RegistrationRequest().register(false).path(registeredPath), AtOnceDispatcher.getInstance(), new ClientSideResponseFuture(future) {
+
 			@Override
-			public void process(Response response) {
-				if (!response.getOk()) {
-					log.error("failed to unsunscribe " + this + ": " + response.getComment());
-					stateFunctor.handle(new FramsticksException().msg("unsubscription failed").arg("comment", response.getComment()));
-					return;
-				}
+			protected void processOk(Response response) {
 				assert response.hasFiles();
 				log.debug("unsunscribed " + this);
-				stateFunctor.call();
+				future.pass(response);
 			}
 		});
@@ -76,7 +73,8 @@
 
 	public void dispatchCall(final List<File> files) {
-		Dispatching.dispatchIfNotActive(dispatcher, new RunAt<C>() {
+		//TODO TEH
+		Dispatching.dispatchIfNotActive(dispatcher, new RunAt<C>(ThrowExceptionHandler.getInstance()) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				eventCallback.call(files);
 			}
Index: java/main/src/main/java/com/framsticks/communication/SubscriptionCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/SubscriptionCallback.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/communication/SubscriptionCallback.java	(revision 97)
@@ -1,8 +1,17 @@
 package com.framsticks.communication;
+
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 
 /**
  * @author Piotr Sniegowski
  */
-public interface SubscriptionCallback<C> {
-	EventCallback subscribed(Subscription<? super C> subscription);
+public abstract class SubscriptionCallback<C> implements ExceptionResultHandler {
+	public abstract EventCallback subscribed(Subscription<? super C> subscription);
+
+	@Override
+	public void handle(FramsticksException exception) {
+		throw exception;
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java	(revision 97)
@@ -1,6 +1,6 @@
 package com.framsticks.communication.util;
 
-import com.framsticks.communication.StateCallback;
-import com.framsticks.util.FramsticksException;
+import com.framsticks.communication.ClientSideResponseFuture;
+import com.framsticks.communication.Response;
 
 import org.apache.log4j.Logger;
@@ -9,5 +9,5 @@
  * @author Piotr Sniegowski
  */
-public class LoggingStateCallback<C> extends StateCallback<C> {
+public class LoggingStateCallback extends ClientSideResponseFuture {
 
 	protected final Logger logger;
@@ -15,16 +15,18 @@
 
 	public LoggingStateCallback(Logger logger, String message) {
+		super(null);
 		this.logger = logger;
 		this.message = message;
 	}
 
+	// @Override
+	// public void handle(FramsticksException e) {
+	// 	logger.error("failed to " + message + " with " + e);
+	// }
+
 	@Override
-	public void handle(FramsticksException e) {
-		logger.error("failed to " + message + " with " + e);
+	protected void processOk(Response response) {
+		logger.debug(message);
 	}
 
-	@Override
-	public void callImpl() {
-		logger.debug(message);
-	}
 }
Index: java/main/src/main/java/com/framsticks/communication/util/LoggingSubscriptionCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/util/LoggingSubscriptionCallback.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/communication/util/LoggingSubscriptionCallback.java	(revision 97)
@@ -9,5 +9,5 @@
  * @author Piotr Sniegowski
  */
-public class LoggingSubscriptionCallback<C> implements SubscriptionCallback<C> {
+public class LoggingSubscriptionCallback<C> extends SubscriptionCallback<C> {
 
 	protected final Logger logger;
Index: java/main/src/main/java/com/framsticks/core/AbstractInstance.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/AbstractInstance.java	(revision 96)
+++ 	(revision )
@@ -1,162 +1,0 @@
-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: java/main/src/main/java/com/framsticks/core/AbstractInstanceListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/AbstractInstanceListener.java	(revision 96)
+++ 	(revision )
@@ -1,25 +1,0 @@
-package com.framsticks.core;
-
-public abstract class AbstractInstanceListener implements InstanceListener {
-
-	@Override
-	public void onListChange(Path path, ListChange change) {
-
-	}
-
-	@Override
-	public void onFetch(Path path) {
-
-	}
-
-	@Override
-	public void onRun(Exception e) {
-
-	}
-
-	@Override
-	public void onStop(Exception e) {
-
-	}
-
-}
Index: java/main/src/main/java/com/framsticks/core/AbstractTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/AbstractTree.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/core/AbstractTree.java	(revision 97)
@@ -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 com.framsticks.util.dispatching.ThrowExceptionHandler;
+
+/**
+ * @author Piotr Sniegowski
+ */
+@FramsClassAnnotation
+public abstract class AbstractTree extends Thread<Tree> implements Tree {
+
+	private static final Logger log = Logger.getLogger(Tree.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<TreeListener> listeners = new HashSet<TreeListener>();
+
+	public AbstractTree() {
+		setName("entity");
+	}
+
+	protected void tryRegisterOnChangeEvents(Path path) {
+
+	}
+
+
+	protected void fireRun(Exception e) {
+		for (TreeListener l : this.listeners) {
+			l.onRun(e);
+		}
+	}
+
+	protected void fireStop(Exception e) {
+		for (TreeListener l : this.listeners) {
+			l.onStop(e);
+		}
+	}
+
+	@Override
+	public void addListener(final TreeListener listener) {
+		assert Dispatching.isThreadSafe();
+		Dispatching.dispatchIfNotActive(this, new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				listeners.add(listener);
+			}
+		});
+	}
+
+	@Override
+	public void removeListener(final TreeListener listener) {
+		assert Dispatching.isThreadSafe();
+		Dispatching.dispatchIfNotActive(this, new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				listeners.remove(listener);
+			}
+		});
+	}
+
+	protected void fireListChange(Path path, ListChange change) {
+		assert isActive();
+		for (TreeListener l : this.listeners) {
+			l.onListChange(path, change);
+		}
+	}
+
+	@Override
+	public void notifyOfFetch(Path path) {
+		fireFetch(path);
+	}
+
+	protected void fireFetch(Path path) {
+		assert isActive();
+		for (TreeListener 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 tree " + this);
+		paramsPackage.register(registry);
+	}
+
+	@AutoAppendAnnotation
+	public void takeFromRegistry(Registry registry) {
+		log.debug("taking from registry " + registry + " in tree " + this);
+		this.registry.takeAllFrom(registry);
+	}
+
+	@Override
+	protected void joinableStart() {
+		dispatch(new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				if (!isRootAssigned()) {
+					setRoot(new Node(Param.build().name("Tree").id(getName()).type("o").finish(CompositeParam.class), null));
+				}
+			}
+		});
+		super.joinableStart();
+	}
+
+	@Override
+	public void putInfoIntoCache(FramsClass framclass) {
+		registry.putFramsClass(framclass);
+	}
+}
+
Index: java/main/src/main/java/com/framsticks/core/AbstractTreeListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/AbstractTreeListener.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/core/AbstractTreeListener.java	(revision 97)
@@ -0,0 +1,25 @@
+package com.framsticks.core;
+
+public abstract class AbstractTreeListener implements TreeListener {
+
+	@Override
+	public void onListChange(Path path, ListChange change) {
+
+	}
+
+	@Override
+	public void onFetch(Path path) {
+
+	}
+
+	@Override
+	public void onRun(Exception e) {
+
+	}
+
+	@Override
+	public void onStop(Exception e) {
+
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/core/Framsticks.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Framsticks.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/core/Framsticks.java	(revision 97)
@@ -29,5 +29,10 @@
 	public static void main(final String[] args) {
 
-		new Monitor(loadConfiguration(Framsticks.class.getResourceAsStream("/configs/framsticks.xml"))).use().waitFor().drop().join();
+		String config = "/configs/framsticks.xml";
+		if (args.length != 0) {
+			config = args[0];
+		}
+
+		new Monitor(loadConfiguration(Framsticks.class.getResourceAsStream(config))).use().waitFor().drop().join();
 
 		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 96)
+++ 	(revision )
@@ -1,55 +1,0 @@
-package com.framsticks.core;
-
-import javax.annotation.Nonnull;
-
-import com.framsticks.params.AccessInterface;
-import com.framsticks.params.CompositeParam;
-import com.framsticks.params.FramsClass;
-import com.framsticks.params.Registry;
-import com.framsticks.params.ValueParam;
-import com.framsticks.params.types.ProcedureParam;
-import com.framsticks.util.StateFunctor;
-import com.framsticks.util.dispatching.Dispatcher;
-import com.framsticks.util.dispatching.Future;
-import com.framsticks.util.dispatching.Joinable;
-
-public interface Instance extends Dispatcher<Instance>, Joinable {
-
-	public @Nonnull Node getRoot();
-	public @Nonnull void setRoot(Node node);
-
-	public @Nonnull AccessInterface prepareAccess(CompositeParam param);
-	public void takeAllFrom(Registry source);
-
-	public void addListener(InstanceListener listener);
-	public void removeListener(InstanceListener listener);
-
-	public void notifyOfFetch(Path path);
-
-	public FramsClass getInfoFromCache(String id);
-
-	public void putInfoIntoCache(FramsClass framclass);
-
-	public void resolve(Path path, Future<Path> future);
-
-	/** This is part of the Instance interface.
-	 *
-	 */
-	public void fetchValue(Path path, ValueParam param, StateFunctor stateFunctor);
-
-	/** This is part of the Instance interface.
-	 *
-	 */
-	public void fetchValues(Path path, StateFunctor stateFunctor);
-
-	/** This is part of the Instance interface.
-	 *
-	 */
-	public void call(Path path, ProcedureParam param, Object[] arguments, Future<Object> future);
-
-	public void storeValue(Path path, ValueParam param, Object value, StateFunctor stateFunctor);
-
-	public void fetchInfo(Path path, Future<FramsClass> future);
-
-	public Path create(Path path);
-}
Index: java/main/src/main/java/com/framsticks/core/InstanceListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/InstanceListener.java	(revision 96)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package com.framsticks.core;
-
-/**
- * @author Piotr Sniegowski
- */
-public interface InstanceListener {
-	public void onListChange(Path path, ListChange change);
-	public void onFetch(Path path);
-	public void onRun(Exception e);
-	public void onStop(Exception e);
-}
Index: java/main/src/main/java/com/framsticks/core/InstanceUtils.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/InstanceUtils.java	(revision 96)
+++ 	(revision )
@@ -1,242 +1,0 @@
-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: java/main/src/main/java/com/framsticks/core/Mode.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Mode.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/core/Mode.java	(revision 97)
@@ -0,0 +1,6 @@
+package com.framsticks.core;
+
+public enum Mode {
+	CACHE,
+	FETCH
+}
Index: java/main/src/main/java/com/framsticks/core/ObjectInstance.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/ObjectInstance.java	(revision 96)
+++ 	(revision )
@@ -1,113 +1,0 @@
-package com.framsticks.core;
-
-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.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 AbstractInstance {
-	private static final Logger log = Logger.getLogger(ObjectInstance.class);
-
-	@AutoAppendAnnotation
-	public void setRootObject(Object object) {
-		registry.registerAndBuild(object.getClass());
-		AccessInterface access = registry.createAccess(object.getClass());
-		setRoot(new Node(Param.build().forAccess(access).id(getName()).finish(CompositeParam.class), object));
-	}
-
-	public Object getRootObject() {
-		return getRoot().getObject();
-	}
-
-	public <T> T getRootObject(Class<T> type) {
-		Object result = getRootObject();
-		if (result == null) {
-			throw new FramsticksException().msg("object instance is empty").arg("instance", this);
-		}
-		if (!type.isInstance(result)) {
-			throw new FramsticksException().msg("object instance holds object of different kind").arg("object", result).arg("requested", type).arg("instance", this);
-		}
-		return type.cast(result);
-	}
-
-	@Override
-	public void fetchValues(final Path path, final StateFunctor stateFunctor) {
-		assert isActive();
-		log.debug("requesting: " + path);
-		fireFetch(path);
-		stateFunctor.call();
-	}
-
-	@Override
-	public void fetchValue(Path path, ValueParam param, StateFunctor stateFunctor) {
-		assert isActive();
-		fireFetch(path);
-		stateFunctor.call();
-	}
-
-	@Override
-	public void call(Path path, ProcedureParam param, Object[] arguments, Future<Object> future) {
-		assert isActive();
-		try {
-			future.pass(InstanceUtils.bindAccess(path).call(param, arguments));
-		} catch (FramsticksException 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/ObjectTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/ObjectTree.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/core/ObjectTree.java	(revision 97)
@@ -0,0 +1,112 @@
+package com.framsticks.core;
+
+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.PrimitiveParam;
+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.dispatching.Future;
+import static com.framsticks.core.TreeOperations.*;
+
+@FramsClassAnnotation
+public class ObjectTree extends AbstractTree {
+	private static final Logger log = Logger.getLogger(ObjectTree.class);
+
+	@AutoAppendAnnotation
+	public void setRootObject(Object object) {
+		registry.registerAndBuild(object.getClass());
+		AccessInterface access = registry.createAccess(object.getClass());
+		setRoot(new Node(Param.build().forAccess(access).id(getName()).finish(CompositeParam.class), object));
+	}
+
+	public Object getRootObject() {
+		return getRoot().getObject();
+	}
+
+	public <T> T getRootObject(Class<T> type) {
+		Object result = getRootObject();
+		if (result == null) {
+			throw new FramsticksException().msg("object tree is empty").arg("tree", this);
+		}
+		if (!type.isInstance(result)) {
+			throw new FramsticksException().msg("object tree holds object of different kind").arg("object", result).arg("requested", type).arg("tree", this);
+		}
+		return type.cast(result);
+	}
+
+	@Override
+	public void get(final Path path, Mode mode, Future<Object> future) {
+		assert isActive();
+		log.debug("requesting: " + path);
+		fireFetch(path);
+		future.pass(path.getTopObject());
+	}
+
+	@Override
+	public void get(Path path, PrimitiveParam<?> param, Mode mode, Future<Object> future) {
+		assert isActive();
+		fireFetch(path);
+		future.pass(bindAccess(path).get(param, Object.class));
+	}
+
+	@Override
+	public void call(Path path, ProcedureParam param, Object[] arguments, Future<Object> future) {
+		assert isActive();
+		try {
+			future.pass(bindAccess(path).call(param, arguments));
+		} catch (FramsticksException e) {
+			future.handle(e);
+		}
+	}
+
+	@Override
+	public void info(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 = 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 set(Path path, PrimitiveParam<?> param, Object value, final Future<Integer> future) {
+		assert isActive();
+		future.pass(bindAccess(path).set(param, value));
+	}
+
+	@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 96)
+++ java/main/src/main/java/com/framsticks/core/Path.java	(revision 97)
@@ -23,9 +23,9 @@
 	// private final static Logger log = Logger.getLogger(Path.class.getName());
 
-	final Instance instance;
+	final Tree tree;
 	final String textual;
 	final LinkedList<Node> nodes;
 
-	protected static Object getKnownChild(Instance instance, AccessInterface access, CompositeParam param) {
+	protected static Object getKnownChild(Tree tree, AccessInterface access, CompositeParam param) {
 		Object child = access.get(param, Object.class);
 		if (child == null) {
@@ -33,5 +33,5 @@
 		}
 		try {
-			instance.prepareAccess(param);
+			tree.prepareAccess(param);
 			return child;
 		} catch (FramsticksException e) {
@@ -41,10 +41,10 @@
 
 	/**
-	 * @param instance
+	 * @param tree
 	 * @param textual
 	 * @param nodes
 	 */
-	Path(Instance instance, String textual, LinkedList<Node> nodes) {
-		this.instance = instance;
+	Path(Tree tree, String textual, LinkedList<Node> nodes) {
+		this.tree = tree;
 		this.textual = textual;
 		this.nodes = nodes;
@@ -53,5 +53,5 @@
 	public Path appendNode(Node node) {
 		assert isResolved();
-		return new PathBuilder().instance(instance).textual(textual + ((size() == 1) ? "" : "/") + node.getParam().getId()).add(nodes).add(node).finish();
+		return new PathBuilder().tree(tree).textual(textual + ((size() == 1) ? "" : "/") + node.getParam().getId()).add(nodes).add(node).finish();
 	}
 
@@ -63,12 +63,12 @@
 	public static class PathBuilder {
 
-		Instance instance;
+		Tree tree;
 		String textual;
 		final LinkedList<Node> nodes = new LinkedList<Node>();
 
 		public Path finish() {
-			assert instance != null;
+			assert tree != null;
 			assert textual != null;
-			return new Path(instance, textual, nodes);
+			return new Path(tree, textual, nodes);
 		}
 
@@ -77,6 +77,6 @@
 		}
 
-		public PathBuilder instance(Instance instance) {
-			this.instance = instance;
+		public PathBuilder tree(Tree tree) {
+			this.tree = tree;
 			return this;
 		}
@@ -130,17 +130,17 @@
 		}
 
-		public PathBuilder resolve(@Nonnull Instance instance, String textual) {
+		public PathBuilder resolve(@Nonnull Tree tree, String textual) {
 
 			assert nodes.isEmpty();
-			assert instance.isActive();
-			this.instance = instance;
-
-			nodes.add(instance.getRoot());
-			Node current = instance.getRoot();
+			assert tree.isActive();
+			this.tree = tree;
+
+			nodes.add(tree.getRoot());
+			Node current = tree.getRoot();
 
 			StringBuilder b = new StringBuilder();
 			Iterator<String> i = splitPath(textual);
 			while (i.hasNext() && current.getObject() != null) {
-				AccessInterface access = instance.prepareAccess(current.getParam());
+				AccessInterface access = tree.prepareAccess(current.getParam());
 				if (access == null) {
 					break;
@@ -155,5 +155,5 @@
 				b.append("/").append(e);
 				access.select(current.getObject());
-				current = new Node(c, getKnownChild(instance, access, c));
+				current = new Node(c, getKnownChild(tree, access, c));
 				nodes.add(current);
 			}
@@ -170,5 +170,5 @@
 	public Path appendResolution(Object object) {
 		assert !isResolved();
-		Path result = new PathBuilder().textual(textual).instance(instance).add(nodes).setLast(object).finish();
+		Path result = new PathBuilder().textual(textual).tree(tree).add(nodes).setLast(object).finish();
 		assert size() == result.size();
 		return result;
@@ -193,5 +193,9 @@
 
 	public String toString() {
-		return instance + textual + (!isResolved() ? "!" : "");
+		return tree + textual + (!isResolved() ? "!" : "");
+	}
+
+	public String getFullTextual() {
+		return tree.getName() + textual;
 	}
 
@@ -216,7 +220,7 @@
 	}
 
-	public final @Nonnull Instance getInstance() {
-		assert Dispatching.isThreadSafe();
-		return instance;
+	public final @Nonnull Tree getTree() {
+		assert Dispatching.isThreadSafe();
+		return tree;
 	}
 
@@ -233,10 +237,10 @@
 	 */
 	public Path tryFindResolution() {
-		assert instance.isActive();
+		assert tree.isActive();
 		assert !isResolved();
 		if (size() == 1) {
-			return Path.build().resolve(instance, "/").finish();//appendResolution(instance.root.object);
-		}
-		Object child = getKnownChild(instance, InstanceUtils.bindAccess(instance, getUnder()), getTop().getParam());
+			return Path.build().resolve(tree, "/").finish();
+		}
+		Object child = getKnownChild(tree, TreeOperations.bindAccess(tree, getUnder()), getTop().getParam());
 		if (child == null) {
 			return this;
@@ -247,5 +251,5 @@
 	public boolean matches(Path p) {
 		assert Dispatching.isThreadSafe();
-		assert instance == p.instance;
+		assert tree == p.tree;
 		Iterator<Node> a = nodes.iterator();
 		Iterator<Node> b = p.nodes.iterator();
@@ -264,11 +268,7 @@
 	}
 
-	public final boolean isOwner(Instance instance) {
-		return this.instance == instance;
-	}
-
-	// public void setInstance(Instance instance) {
-	//	this.instance = instance;
-	// }
+	public final boolean isOwner(Tree tree) {
+		return this.tree == tree;
+	}
 
 	@SuppressWarnings("unchecked")
@@ -284,6 +284,6 @@
 	}
 
-	public static Path to(@Nonnull Instance instance, String textual) {
-		return Path.build().resolve(instance, textual).finish();
+	public static Path to(@Nonnull Tree tree, String textual) {
+		return Path.build().resolve(tree, textual).finish();
 	}
 }
Index: java/main/src/main/java/com/framsticks/core/Tree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Tree.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/core/Tree.java	(revision 97)
@@ -0,0 +1,45 @@
+package com.framsticks.core;
+
+import javax.annotation.Nonnull;
+
+import com.framsticks.params.AccessInterface;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.Registry;
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.Joinable;
+
+public interface Tree extends Dispatcher<Tree>, Joinable {
+
+	public @Nonnull Node getRoot();
+	public @Nonnull void setRoot(Node node);
+
+	public @Nonnull AccessInterface prepareAccess(CompositeParam param);
+	public void takeAllFrom(Registry source);
+
+	public void addListener(TreeListener listener);
+	public void removeListener(TreeListener listener);
+
+	public void notifyOfFetch(Path path);
+
+	public FramsClass getInfoFromCache(String id);
+
+	public void putInfoIntoCache(FramsClass framclass);
+
+	public void resolve(Path path, Future<Path> future);
+
+	public void get(Path path, PrimitiveParam<?> param, Mode mode, Future<Object> future);
+
+	public void get(Path path, Mode mode, Future<Object> future);
+
+	public void call(Path path, ProcedureParam param, Object[] arguments, Future<Object> future);
+
+	public void set(Path path, PrimitiveParam<?> param, Object value, Future<Integer> future);
+
+	public void info(Path path, Future<FramsClass> future);
+
+	public Path create(Path path);
+}
Index: java/main/src/main/java/com/framsticks/core/TreeListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/TreeListener.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/core/TreeListener.java	(revision 97)
@@ -0,0 +1,11 @@
+package com.framsticks.core;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public interface TreeListener {
+	public void onListChange(Path path, ListChange change);
+	public void onFetch(Path path);
+	public void onRun(Exception e);
+	public void onStop(Exception e);
+}
Index: java/main/src/main/java/com/framsticks/core/TreeOperations.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/TreeOperations.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/core/TreeOperations.java	(revision 97)
@@ -0,0 +1,246 @@
+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.PrimitiveParam;
+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.FramsticksException;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.RunAt;
+
+import static com.framsticks.util.dispatching.Dispatching.*;
+
+public final class TreeOperations {
+
+	private static final Logger log = Logger.getLogger(TreeOperations.class.getName());
+
+	private TreeOperations() {
+	}
+
+	public static @Nonnull FramsClass processFetchedInfo(Tree tree, File file) {
+		assert tree.isActive();
+		FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
+		if ("/".equals(file.getPath())) {
+			if (tree.getRoot().getParam().getContainedTypeName() == null) {
+				tree.setRoot(new Node(Param.build().name("Tree").id(tree.getName()).type("o " + framsClass.getId()).finish(CompositeParam.class), tree.getRoot().getObject()));
+			}
+		}
+		tree.putInfoIntoCache(framsClass);
+		return framsClass;
+	}
+
+	public static FramsClass getInfo(Path path) {
+		Tree tree = path.getTree();
+		assert tree.isActive();
+		final String name = path.getTop().getParam().getContainedTypeName();
+		return tree.getInfoFromCache(name);
+	}
+
+	public static void findInfo(final Path path, final Future<FramsClass> future) {
+		try {
+			Tree tree = path.getTree();
+			assert tree.isActive();
+			final FramsClass framsClass = getInfo(path);
+			if (framsClass != null) {
+				future.pass(framsClass);
+				return;
+			}
+			tree.info(path, future);
+		} catch (FramsticksException e) {
+			future.handle(e);
+		}
+	}
+
+	public static void processFetchedValues(Path path, List<File> files) {
+		Tree tree = path.getTree();
+		assert tree.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(TreeOperations.bindAccess(tree, node));
+				loader.go();
+				tree.notifyOfFetch(path);
+				return;
+			}
+
+			ListAccess listAccess = ((ListAccess) TreeOperations.bindAccess(tree, 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;
+					TreeOperations.bindAccess(tree, node).set((ValueParam) param, child);
+				}
+			}
+
+			tree.notifyOfFetch(path);
+		} catch (Exception e) {
+			log.error("exception occurred while loading: " + e);
+		}
+
+	}
+
+	public static void resolveAndGet(final Tree tree, final String targetPath, final Future<Path> future) {
+		resolve(tree, targetPath, new FutureHandler<Path>(future) {
+			@Override
+			protected void result(final Path path) {
+				assert path.isResolved(targetPath);
+				//TODO Future
+				tree.get(path, Mode.FETCH, new FutureHandler<Object>(future) {
+					@Override
+					protected void result(Object object) {
+						future.pass(path);
+					}
+				});
+			}
+		});
+	}
+
+
+	public static void resolve(final Path path, final Future<Path> future) {
+		final Tree tree = path.getTree();
+		assert tree.isActive();
+		if (path.getTop().getObject() != null) {
+			if (getInfoFromCache(path) != null) {
+				future.pass(path);
+				return;
+			}
+			TreeOperations.findInfo(path, new FutureHandler<FramsClass>(future) {
+				@Override
+				protected void result(FramsClass result) {
+					future.pass(path);
+				}
+			});
+			return;
+		}
+		TreeOperations.findInfo(path, new FutureHandler<FramsClass>(future) {
+			@Override
+			protected void result(FramsClass result) {
+				assert tree.isActive();
+				assert path.getTop().getParam().isMatchingContainedName(result.getId());
+				Path p = (path.getTop().getParam().getContainedTypeName() != null ? path : path.tryFindResolution());
+				future.pass(TreeOperations.createIfNeeded(p));
+			}
+		});
+	}
+
+	public static Path createIfNeeded(Tree tree, String path) {
+		assert tree.isActive();
+		Path p;
+		while (!(p = Path.to(tree, path)).isResolved(path)) {
+			tree.create(p);
+		}
+		return p;
+	}
+
+	public static Path createIfNeeded(Path path) {
+		Tree tree = path.getTree();
+		assert tree.isActive();
+		if (path.isResolved()) {
+			return path;
+		}
+		return tree.create(path);
+	}
+
+	public static @Nonnull AccessInterface bindAccess(Tree tree, String path) {
+		return bindAccess(Path.to(tree, path));
+	}
+
+	public static @Nonnull AccessInterface bindAccess(Tree tree, Node node) {
+		assert tree.isActive();
+		assert node.getObject() != null;
+
+		try {
+			return tree.prepareAccess(node.getParam()).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.getTree().isActive();
+		path.assureResolved();
+		return bindAccess(path.getTree(), path.getTop());
+	}
+
+	public static void set(final Path path, final PrimitiveParam<?> param, final Object value, final Future<Integer> future) {
+		final Tree tree = path.getTree();
+
+		dispatchIfNotActive(tree, new RunAt<Tree>(future) {
+			@Override
+			protected void runAt() {
+				tree.set(path, param, value, future);
+			}
+		});
+	}
+
+	public static void call(final Path path, final ProcedureParam param, final Object[] arguments, final Future<Object> future) {
+		final Tree tree = path.getTree();
+
+		dispatchIfNotActive(tree, new RunAt<Tree>(future) {
+			@Override
+			protected void runAt() {
+				tree.call(path, param, arguments, future);
+			}
+		});
+	}
+
+	/** This might not be correct. */
+	public static void resolve(final Tree tree, final String targetPath, final Future<Path> future) {
+		dispatchIfNotActive(tree, new RunAt<Tree>(future) {
+
+			@Override
+			protected void runAt() {
+				tree.resolve(Path.to(tree, targetPath), new FutureHandler<Path>(future) {
+					@Override
+					protected void result(Path result) {
+						assert result.getTree().isActive();
+						if (result.isResolved(targetPath)) {
+							future.pass(result);
+							return;
+						}
+						resolve(tree, targetPath, future);
+					}
+				});
+			}
+		});
+	}
+
+	public static FramsClass getInfoFromCache(Path path) {
+		assert path.getTree().isActive();
+		return path.getTree().getInfoFromCache(path.getTop().getParam().getContainedTypeName());
+	}
+}
Index: java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java
===================================================================
--- java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java	(revision 97)
@@ -11,6 +11,6 @@
 import org.apache.log4j.Logger;
 
-import com.framsticks.core.AbstractInstanceListener;
-import com.framsticks.core.Instance;
+import com.framsticks.core.AbstractTreeListener;
+import com.framsticks.core.Tree;
 import com.framsticks.core.Path;
 import com.framsticks.dumping.PrintWriterSink;
@@ -19,8 +19,9 @@
 import com.framsticks.remote.RecursiveFetcher;
 import com.framsticks.util.FramsticksException;
-import com.framsticks.util.Logging;
 import com.framsticks.util.PeriodicTask;
-import com.framsticks.util.StateFunctor;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.FutureHandler;
 import com.framsticks.util.dispatching.JoinableCollection;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
 import com.framsticks.util.io.Encoding;
 
@@ -28,5 +29,5 @@
  * @author Piotr Sniegowski
  */
-public class Diagnostics extends JoinableCollection<Instance> {
+public class Diagnostics extends JoinableCollection<Tree> {
 	private static final Logger log = Logger.getLogger(Diagnostics.class);
 
@@ -41,10 +42,11 @@
 
 
+
 	@Override
 	@AutoAppendAnnotation
-	public void add(final Instance instance) {
-		super.add(instance);
+	public void add(final Tree tree) {
+		super.add(tree);
 
-		instance.addListener(new AbstractInstanceListener() {
+		tree.addListener(new AbstractTreeListener() {
 			@Override
 			public void onRun(Exception e) {
@@ -54,39 +56,36 @@
 
 				if (dumpsInterval != null) {
-					new PeriodicTask<Instance>(instance, dumpsInterval * 1000) {
+					new PeriodicTask<Tree>(ThrowExceptionHandler.getInstance(), tree, dumpsInterval * 1000) {
+						protected final ExceptionResultHandler repeater = new ExceptionResultHandler() {
+
+							@Override
+							public void handle(FramsticksException exception) {
+								log.error("caught error during diagnostics fetching (repeating): " + exception);
+								again();
+							}
+
+						};
 						@Override
-						public void run() {
+						protected void runAt() {
 
 							log.info("starting periodic dump");
-							new RecursiveFetcher(instance, Path.to(instance, "/"), new StateFunctor() {
-								@Override
-								public void handle(FramsticksException e) {
-									Logging.log(log, "recursively fetch", instance, e);
-									again();
-								}
+							new RecursiveFetcher(tree, Path.to(tree, "/"), new FutureHandler<Void>(repeater) {
 
 								@Override
-								public void call() {
-									log.info("instance resolved, saving");
+								protected void result(Void result) {
+									log.info("tree resolved, saving");
 									try {
-										final String fileName = dumpsPath + "/" + instance + "_" + new SimpleDateFormat(dumpsFormat).format(new Date()) + ".param";
+										final String fileName = dumpsPath + "/" + tree + "_" + 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, Path.to(instance, "/"), new StateFunctor() {
-											@Override
-											public void handle(FramsticksException e) {
-												Logging.log(log, "periodic dump in " + fileName + " of", instance, e);
-												again();
-											}
+										new SaveStream(new PrintWriterSink(new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), Encoding.getFramsticksCharset()))), tree, Path.to(tree, "/"), new FutureHandler<Void>(repeater) {
 
 											@Override
-											public void call() {
+											protected void result(Void result) {
 												again();
 											}
 										});
-									} catch (IOException ex) {
-										log.info("failed to initiate dump: " + ex);
-										again();
+									} catch (IOException e) {
+										throw new FramsticksException().msg("failed to initiate dump").cause(e);
 									}
-
 								}
 							});
Index: java/main/src/main/java/com/framsticks/dumping/LoadStream.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/LoadStream.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/dumping/LoadStream.java	(revision 97)
@@ -2,8 +2,8 @@
 
 import com.framsticks.communication.File;
-import com.framsticks.core.InstanceUtils;
+import com.framsticks.core.TreeOperations;
 import com.framsticks.core.Path;
 import com.framsticks.params.ListSource;
-import com.framsticks.core.Instance;
+import com.framsticks.core.Tree;
 import com.framsticks.util.*;
 import com.framsticks.util.dispatching.Future;
@@ -24,5 +24,5 @@
 	private final static Logger log = Logger.getLogger(LoadStream.class.getName());
 
-	protected final Instance instance;
+	protected final Tree tree;
 	protected final Path mountPath;
 	protected final BufferedReader stream;
@@ -31,6 +31,6 @@
 
 
-	public LoadStream(Path mountPath, BufferedReader stream, Instance instance, Future<Path> future) {
-		this.instance = instance;
+	public LoadStream(Path mountPath, BufferedReader stream, Tree tree, Future<Path> future) {
+		this.tree = tree;
 		this.mountPath = mountPath;
 		this.stream = stream;
@@ -59,9 +59,9 @@
 					if (line.equals("ok")) {
 						if (query.first.equals("get")) {
-							Path path = InstanceUtils.createIfNeeded(instance, query.second);
-							InstanceUtils.processFetchedValues(path, files);
+							Path path = TreeOperations.createIfNeeded(tree, query.second);
+							TreeOperations.processFetchedValues(path, files);
 						} else if (query.first.equals("info")) {
 							assert files.size() == 1;
-							InstanceUtils.processFetchedInfo(instance, files.get(0));
+							TreeOperations.processFetchedInfo(tree, files.get(0));
 						} else {
 							assert false;
@@ -87,5 +87,5 @@
 		}
 		log.info("loaded in: " + stopwatch);
-		future.pass(Path.to(instance, mountPath.getTextual()));
+		future.pass(Path.to(tree, mountPath.getTextual()));
 	}
 
Index: java/main/src/main/java/com/framsticks/dumping/SaveStream.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 97)
@@ -1,5 +1,5 @@
 package com.framsticks.dumping;
 
-import static com.framsticks.core.InstanceUtils.*;
+import static com.framsticks.core.TreeOperations.*;
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
@@ -10,7 +10,10 @@
 import com.framsticks.params.SinkInterface;
 import com.framsticks.parsers.Savers;
-import com.framsticks.core.Instance;
+import com.framsticks.core.Tree;
 import com.framsticks.util.*;
 import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+
 import org.apache.log4j.Logger;
 import com.framsticks.util.dispatching.RunAt;
@@ -28,6 +31,6 @@
 
 	protected final SinkInterface sink;
-	protected final Instance instance;
-	protected final StateFunctor stateFunctor;
+	protected final Tree tree;
+	protected final Future<Void> future;
 	protected final Stopwatch stopwatch = new Stopwatch();
 	protected final Set<FramsClass> storedInfo = new HashSet<FramsClass>();
@@ -35,9 +38,9 @@
 	private int dispatched = 0;
 
-	public SaveStream(SinkInterface sink, Instance instance, Path root, StateFunctor stateFunctor) {
+	public SaveStream(SinkInterface sink, Tree tree, Path root, Future<Void> future) {
 		assert Dispatching.isThreadSafe();
 		this.sink = sink;
-		this.instance = instance;
-		this.stateFunctor = stateFunctor;
+		this.tree = tree;
+		this.future = future;
 		dispatchWrite(root);
 	}
@@ -45,7 +48,8 @@
 	protected void dispatchWrite(final Path path) {
 		++dispatched;
-		instance.dispatch(new RunAt<Instance>() {
+		//TODO TEH
+		tree.dispatch(new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				write(path);
 			}
@@ -54,11 +58,11 @@
 
 	protected void finished() {
-		assert instance.isActive();
+		assert tree.isActive();
 		log.info("stored in " + stopwatch);
-		stateFunctor.call();
+		future.pass(null);
 	}
 
 	public void write(final Path path) {
-		assert instance.isActive();
+		assert tree.isActive();
 		if (!path.isResolved()) {
 			log.debug("path " + path + " is not resolved - skipping");
Index: java/main/src/main/java/com/framsticks/gui/Browser.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 97)
@@ -2,11 +2,17 @@
 
 import com.framsticks.core.*;
+import com.framsticks.gui.console.Console;
+import com.framsticks.gui.console.TrackConsole;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.remote.RemoteTree;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.dispatching.AbstractJoinable;
 import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
 import com.framsticks.util.dispatching.Joinable;
 import com.framsticks.util.dispatching.JoinableCollection;
@@ -19,5 +25,9 @@
 
 import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 import com.framsticks.util.dispatching.RunAt;
@@ -27,13 +37,16 @@
  */
 @FramsClassAnnotation
-public class Browser extends AbstractJoinable implements Dispatcher<Browser>, JoinableParent {
-
-	private static final Logger log = Logger.getLogger(Browser.class.getName());
-
-	protected JoinableCollection<Frame> frames = new JoinableCollection<Frame>().setObservableName("frames");
-	protected JoinableCollection<Instance> instances = new JoinableCollection<Instance>().setObservableName("instances");
-
-	protected MainFrame mainFrame;
-	public List<PanelProvider> panelProviders = new ArrayList<PanelProvider>();
+public class Browser extends AbstractJoinable implements Dispatcher<Browser>, JoinableParent, ExceptionResultHandler {
+
+	private static final Logger log = Logger.getLogger(Browser.class);
+
+	protected final JoinableCollection<Frame> frames = new JoinableCollection<Frame>().setObservableName("frames");
+	protected final JoinableCollection<Tree> trees = new JoinableCollection<Tree>().setObservableName("trees");
+	protected final JoinableCollection<Console> consoles = new JoinableCollection<Console>().setObservableName("consoles");
+
+	protected final List<PopupMenuEntryProvider> popupMenuEntryProviders = new LinkedList<>();
+
+	protected final MainFrame mainFrame;
+	protected final List<PanelProvider> panelProviders = new ArrayList<PanelProvider>();
 	protected Dimension defaultFrameDimension;
 
@@ -51,4 +64,44 @@
 		mainFrame = new MainFrame(Browser.this);
 		addFrame(mainFrame);
+
+		addPopupMenuEntryProvider(new PopupMenuEntryProvider() {
+			@Override
+			public void provide(JPopupMenu menu, Path path) {
+				menu.add(new JMenuItem(path.getFullTextual()));
+				menu.addSeparator();
+			}
+		});
+
+		addPopupMenuEntryProvider(new PopupMenuEntryProvider() {
+			@SuppressWarnings("serial")
+			@Override
+			public void provide(JPopupMenu menu, final Path path) {
+				menu.add(new AbstractAction("Copy path to clipboard") {
+					@Override
+					public void actionPerformed(ActionEvent e) {
+						Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(path.getFullTextual()), null);
+					}
+				});
+			}
+		});
+
+		addPopupMenuEntryProvider(new PopupMenuEntryProvider() {
+			@SuppressWarnings("serial")
+			@Override
+			public void provide(JPopupMenu menu, final Path path) {
+				if (!(path.getTree() instanceof RemoteTree)) {
+					return;
+				}
+				final RemoteTree remoteTree = (RemoteTree) path.getTree();
+				menu.add(new AbstractAction("Open tracking console") {
+					@Override
+					public void actionPerformed(ActionEvent e) {
+						consoles.add(new TrackConsole().setConnection(remoteTree.getConnection()));
+					}
+				});
+			}
+		});
+		// addNodeActionToTreePopupMenu("", new NodeAction() )
+
 	}
 
@@ -60,21 +113,26 @@
 
 	@AutoAppendAnnotation
-	public void addInstance(Instance instance) {
-		log.info("adding instance: " + instance);
-		instances.add(instance);
+	public void addPopupMenuEntryProvider(PopupMenuEntryProvider popupMenuEntryProvider) {
+		popupMenuEntryProviders.add(popupMenuEntryProvider);
+	}
+
+	@AutoAppendAnnotation
+	public void addTree(Tree tree) {
+		log.info("adding tree: " + tree);
+		trees.add(tree);
 	}
 
 	public void autoResolvePath(final String path, final Future<Path> future) {
-		final Instance i = instances.get("localhost");
-		i.dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				InstanceUtils.resolveAndFetch(i, path, new Future<Path>(future) {
+		final Tree i = trees.get("localhost");
+		i.dispatch(new RunAt<Tree>(future) {
+			@Override
+			protected void runAt() {
+				TreeOperations.resolveAndGet(i, path, new FutureHandler<Path>(future) {
 					@Override
 					protected void result(final Path p) {
 						future.pass(p);
-						mainFrame.dispatch(new RunAt<Frame>() {
+						mainFrame.dispatch(new RunAt<Frame>(future) {
 							@Override
-							public void run() {
+							protected void runAt() {
 								mainFrame.goTo(p);
 							}
@@ -93,58 +151,7 @@
 	}
 
-	protected void initializeGUI() {
-		assert isActive();
-		log.debug("executing first task");
-
-		try {
-			boolean found = false;
-			// for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
-			//	log.info("look and feel available: " + info.getName());
-			//	if ("Nimbus".equals(info.getName())) {
-			//		UIManager.setLookAndFeel(info.getClassName());
-			//		found = true;
-			//		break;
-			//	}
-			// }
-			if (!found) {
-				UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
-			}
-		} catch (Exception ex) {
-			log.warn("failed loading Look&Feel: ", ex);
-		}
-
-		javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
-
-
-		for (Frame f : frames) {
-			f.configure();
-		}
-
-		for (final Instance i : instances) {
-			i.dispatch(new RunAt<Instance>() {
-				@Override
-				public void run() {
-					final Path p = Path.to(i, "/");
-					dispatch(new RunAt<Browser>() {
-						@Override
-						public void run() {
-							mainFrame.addRootPath(p);
-						}
-					});
-				}
-			});
-		}
-
-		for (Frame f : frames) {
-			f.getSwing().setVisible(true);
-		}
-
-		// autoResolvePath("/simulator/genepools/groups/0", null);
-		// autoResolvePath("/", null);
-	}
-
 	public void createTreeNodeForChild(final Path path) {
 		assert !isActive();
-		//assert instance.isActive();
+		//assert tree.isActive();
 
 		/*
@@ -174,19 +181,34 @@
 	protected void joinableStart() {
 		Dispatching.use(frames, this);
-		Dispatching.use(instances, this);
-
-		dispatch(new RunAt<Browser>() {
-			@Override
-			public void run() {
-				initializeGUI();
-			}
-		});
-	}
-
-	/**
-	 * @return the instances
-	 */
-	public JoinableCollection<Instance> getInstances() {
-		return instances;
+		Dispatching.use(trees, this);
+		Dispatching.use(consoles, this);
+
+		dispatch(new RunAt<Browser>(this) {
+			@Override
+			protected void runAt() {
+
+				for (final Tree i : trees) {
+					i.dispatch(new RunAt<Tree>(this) {
+						@Override
+						protected void runAt() {
+							final Path p = Path.to(i, "/");
+							dispatch(new RunAt<Browser>(this) {
+								@Override
+								protected void runAt() {
+									mainFrame.addRootPath(p);
+								}
+							});
+						}
+					});
+				}
+			}
+		});
+	}
+
+	/**
+	 * @return the tree
+	 */
+	public JoinableCollection<Tree> getTrees() {
+		return trees;
 	}
 
@@ -227,5 +249,6 @@
 	protected void joinableJoin() throws InterruptedException {
 		Dispatching.join(frames);
-		Dispatching.join(instances);
+		Dispatching.join(trees);
+		Dispatching.join(consoles);
 		// super.join();
 	}
@@ -233,6 +256,7 @@
 	@Override
 	protected void joinableInterrupt() {
+		Dispatching.drop(consoles, this);
 		Dispatching.drop(frames, this);
-		Dispatching.drop(instances, this);
+		Dispatching.drop(trees, this);
 	}
 
@@ -255,8 +279,12 @@
 	}
 
+	@Override
+	public void handle(FramsticksException exception) {
+		mainFrame.handle(exception);
+	}
 
 	// @Override
 	// public boolean isDone() {
-	//	return frames.isDone() && instances.isDone();
+	//	return frames.isDone() && trees.isDone();
 	// }
 }
Index: java/main/src/main/java/com/framsticks/gui/Frame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 97)
@@ -1,29 +1,57 @@
 package com.framsticks.gui;
 
-import com.framsticks.core.Instance;
-import com.framsticks.core.Path;
-import com.framsticks.gui.view.*;
-import com.framsticks.gui.view.TreeCellRenderer;
-import com.framsticks.util.dispatching.Dispatcher;
-import com.framsticks.util.dispatching.JoinableCollection;
-import com.framsticks.util.lang.ScopeEnd;
-import com.framsticks.util.swing.KeyboardModifier;
-import com.framsticks.util.swing.MenuConstructor;
-
-import org.apache.log4j.Logger;
-
-import javax.swing.*;
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTree;
+import javax.swing.KeyStroke;
+import javax.swing.ToolTipManager;
+import javax.swing.UIManager;
 import javax.swing.event.TreeModelEvent;
 import javax.swing.event.TreeModelListener;
 import javax.swing.event.TreeSelectionEvent;
 import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.*;
-
-import java.awt.*;
-import java.awt.datatransfer.StringSelection;
-import java.awt.event.*;
-import java.util.HashMap;
-import java.util.Map;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.DefaultTreeSelectionModel;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.core.Path;
+import com.framsticks.core.Tree;
+import com.framsticks.gui.view.TreeCellRenderer;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableCollection;
+import com.framsticks.util.dispatching.JoinableParent;
+import com.framsticks.util.dispatching.JoinableState;
 import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.lang.ScopeEnd;
+import com.framsticks.util.swing.KeyboardModifier;
+import com.framsticks.util.swing.MenuConstructor;
 
 /**
@@ -31,5 +59,5 @@
  */
 @SuppressWarnings("serial")
-public class Frame extends JoinableCollection<Instance> implements Dispatcher<Frame> {
+public class Frame extends FrameJoinable implements JoinableParent {
 
 	private static final Logger log = Logger.getLogger(Frame.class.getName());
@@ -42,11 +70,8 @@
 	protected JPanel cardPanel;
 
-	protected final String title;
-	protected JFrame swing;
 	protected JScrollPane treeScrollPane;
-	protected JTree tree;
+	protected JTree jtree;
 	protected DefaultTreeModel treeModel;
 	protected javax.swing.tree.MutableTreeNode rootNode;
-	//final Instance instance;
 	protected JPanel treePanel;
 	protected JPopupMenu treePopupMenu;
@@ -54,5 +79,4 @@
 
 	TreeNode currentlyPoppedTreeNode;
-	protected JLabel statusBar;
 	protected JPanel mainPanel;
 	protected JPanel leftPanel;
@@ -67,21 +91,13 @@
 	protected JMenu helpMenu;
 
-	protected final Map<Instance, InstanceAtFrame> instancesAtFrames = new HashMap<Instance, InstanceAtFrame>();
-
-	public Frame(String title, Browser browser) {
-		this.title = title;
+	protected final Map<Tree, TreeAtFrame> treeAtFrames = new HashMap<Tree, TreeAtFrame>();
+	protected JoinableCollection<Tree> trees = new JoinableCollection<Tree>();
+
+	public Frame(Browser browser) {
 		this.browser = browser;
 	}
 
-	public void configure() {
-		swing = new JFrame(title);
-		swing.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
-		swing.addWindowListener(new WindowAdapter() {
-			@Override
-			public void windowClosing(WindowEvent e) {
-				log.info("received closing");
-				interrupt();
-			}
-		});
+	protected void initializeGui() {
+		super.initializeGui();
 		/** this is done to remove the current value label from above the slider,
 		 * because it cannot put to work properly with floating-point value sliders,
@@ -90,33 +106,8 @@
 		log.debug("creating " + this);
 
-		statusBar = new JLabel("not connected");
-
-		Container contentPane = swing.getContentPane();
-		contentPane.setLayout(new BorderLayout());
-
+
+		Container contentPane = getSwing().getContentPane();
 		treePopupMenu = new JPopupMenu("title");
 		treePopupMenu.setName("popup");
-		treePopupMenuHeader = new JMenuItem();
-		treePopupMenuHeader.setForeground(Color.BLUE);
-		treePopupMenu.add(treePopupMenuHeader);
-		treePopupMenu.addSeparator();
-		//TODO: add to favourites
-		//TODO: remove from favourites
-		//TODO: open in new window as root
-		//TODO: refresh
-		//TODO: open in console
-
-		treePopupMenu.add(new JMenuItem("Refresh"));
-		treePopupMenu.add(new JMenuItem("Open in new frame as root"));
-		addNodeActionToTreePopupMenu("Copy path to clipboard", new NodeAction() {
-			@Override
-			public void actionPerformed(TreeNode treeNode) {
-				Path path = treeNode.getInstancePath();
-				StringSelection selection = new StringSelection(path.toString());
-				swing.getToolkit().getSystemClipboard().setContents(selection, selection);
-			}
-		});
-		//this.add(createMenuItem("Add to favourites", null));
-		//this.add(createMenuItem("Remove from favourites", null));
 
 		treePanel = new JPanel();
@@ -147,12 +138,12 @@
 		});
 
-		tree = new JTree(treeModel);
-		tree.setName("tree");
-		tree.setRootVisible(false);
-		tree.setExpandsSelectedPaths(true);
-		tree.setSelectionModel(new DefaultTreeSelectionModel());
-		ToolTipManager.sharedInstance().registerComponent(tree);
-
-		tree.addTreeSelectionListener(new TreeSelectionListener() {
+		jtree = new JTree(treeModel);
+		jtree.setName("tree");
+		jtree.setRootVisible(false);
+		jtree.setExpandsSelectedPaths(true);
+		jtree.setSelectionModel(new DefaultTreeSelectionModel());
+		ToolTipManager.sharedInstance().registerComponent(jtree);
+
+		jtree.addTreeSelectionListener(new TreeSelectionListener() {
 			@Override
 			public void valueChanged(TreeSelectionEvent e) {
@@ -161,12 +152,12 @@
 		});
 
-		tree.setExpandsSelectedPaths(true);
-		tree.setEditable(false);
-		tree.setDoubleBuffered(true);
-		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
-		tree.setShowsRootHandles(true);
-		tree.setRowHeight(26);
-		tree.setDoubleBuffered(true);
-		tree.addMouseListener(new MouseAdapter() {
+		jtree.setExpandsSelectedPaths(true);
+		jtree.setEditable(false);
+		jtree.setDoubleBuffered(true);
+		jtree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+		jtree.setShowsRootHandles(true);
+		jtree.setRowHeight(26);
+		jtree.setDoubleBuffered(true);
+		jtree.addMouseListener(new MouseAdapter() {
 			@Override
 			public void mousePressed(MouseEvent e) {
@@ -182,9 +173,9 @@
 		});
 
-		new KeyboardModifier(tree, JComponent.WHEN_FOCUSED).join(KeyStroke.getKeyStroke('h'), KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)).join(KeyStroke.getKeyStroke('j'), KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)).join(KeyStroke.getKeyStroke('k'), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)).join(KeyStroke.getKeyStroke('l'), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
-
-		tree.setCellRenderer(new TreeCellRenderer());
-
-		treeScrollPane = new JScrollPane(tree);
+		new KeyboardModifier(jtree, JComponent.WHEN_FOCUSED).join(KeyStroke.getKeyStroke('h'), KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)).join(KeyStroke.getKeyStroke('j'), KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)).join(KeyStroke.getKeyStroke('k'), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)).join(KeyStroke.getKeyStroke('l'), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
+
+		jtree.setCellRenderer(new TreeCellRenderer());
+
+		treeScrollPane = new JScrollPane(jtree);
 		treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
 
@@ -215,5 +206,4 @@
 		contentPane.add(menuBar, BorderLayout.NORTH);
 		contentPane.add(mainPanel, BorderLayout.CENTER);
-		contentPane.add(statusBar, BorderLayout.SOUTH);
 
 		leftPanel = new JPanel();
@@ -246,6 +236,6 @@
 		cardPanel.setLayout(cardPanelLayout);
 
-		swing.pack();
-		tree.requestFocusInWindow();
+		getSwing().pack();
+		jtree.requestFocusInWindow();
 
 		log.debug("frame configured: " + this);
@@ -266,45 +256,16 @@
 	public void addRootPath(Path path) {
 		assert isActive();
-		Instance instance = path.getInstance();
-		assert browser.getInstances().contains(instance);
-
-		InstanceAtFrame e = new InstanceAtFrame(instance, this);
-		instance.addListener(e);
-		instancesAtFrames.put(instance, e);
+		Tree tree = path.getTree();
+		assert browser.getTrees().contains(tree);
+
+		TreeAtFrame e = new TreeAtFrame(tree, this);
+		tree.addListener(e);
+		treeAtFrames.put(tree, e);
 		TreeNode node = new TreeNode(e, path);
 		e.rootTreeNode = node;
 		treeModel.insertNodeInto(node, rootNode, rootNode.getChildCount());
-		tree.expandPath(new TreePath(rootNode));
-	}
-
-	@Override
-	public boolean isActive() {
-		return SwingDispatcher.instance.isActive();
-	}
-
-	@Override
-	public void dispatch(RunAt<? extends Frame> runnable) {
-		SwingDispatcher.getInstance().dispatch(runnable);
-	}
-
-	public Action addActionToTreePopupMenu(Action action) {
-		assert isActive();
-		treePopupMenu.add(action);
-		return action;
-	}
-
-	public Action addNodeActionToTreePopupMenu(String title, final NodeAction nodeAction) {
-		assert isActive();
-		return addActionToTreePopupMenu(new AbstractAction(title) {
-			@Override
-			public void actionPerformed(ActionEvent e) {
-				TreeNode treeNode = getCurrentlyPoppedTreeNode();
-				if (treeNode == null) {
-					return;
-				}
-				nodeAction.actionPerformed(treeNode);
-			}
-		});
-	}
+		jtree.expandPath(new TreePath(rootNode));
+	}
+
 
 	public void showPanel(Panel panel) {
@@ -319,18 +280,18 @@
 			return;
 		}
-		currentlyPoppedTreeNode = findTreeNodeByTreePath(tree.getPathForLocation(e.getX(), e.getY()));
+		currentlyPoppedTreeNode = findTreeNodeByTreePath(jtree.getPathForLocation(e.getX(), e.getY()));
 		if (currentlyPoppedTreeNode == null) {
 			return;
 		}
+
+		Path path = currentlyPoppedTreeNode.getTreePath();
+		treePopupMenu.removeAll();
+
+		for (PopupMenuEntryProvider provider : browser.popupMenuEntryProviders) {
+			provider.provide(treePopupMenu, path);
+		}
+		// treePopupMenuHeader.setText(path.getTree().getName() + path.getTextual());
 		treePopupMenu.show(e.getComponent(), e.getX(), e.getY());
 		//currentlyPoppedPanel.getNode().getFramsClass().getName()
-		//treePopupMenuHeader.setText(currentlyPoppedTreeNode.getNode().getPath());
-	}
-
-	/**
-	 * @return the swing
-	 */
-	public JFrame getSwing() {
-		return swing;
 	}
 
@@ -344,10 +305,10 @@
 		cardPanel.removeAll();
 		cardPanel.updateUI();
-		tree.setEnabled(false);
+		jtree.setEnabled(false);
 	}
 
 	public ScopeEnd startChange(final DefaultMutableTreeNode node) {
 		assert isActive();
-		final TreePath selection = tree.getSelectionPath();
+		final TreePath selection = jtree.getSelectionPath();
 		return new ScopeEnd() {
 			@Override
@@ -355,5 +316,5 @@
 				assert isActive();
 				treeModel.nodeChanged(node);
-				tree.setSelectionPath(selection);
+				jtree.setSelectionPath(selection);
 			}
 		};
@@ -391,18 +352,28 @@
 	}
 
+	protected final ExceptionResultHandler dialogHandler = new ExceptionResultHandler() {
+
+		@Override
+		public void handle(FramsticksException exception) {
+			//TODO TEH
+			throw exception;
+
+		}
+	};
+
 	public void goTo(Path path) {
 		assert isActive();
-		final TreePath treePath = instancesAtFrames.get(path.getInstance()).getTreePath(path, false);
+		final TreePath treePath = treeAtFrames.get(path.getTree()).getTreePath(path, false);
 		log.info("go to path: " + path + "(" + treePath + ")");
 
-		new RunAt<Frame>(this) {
-			@Override
-			public void run() {
+		this.dispatch(new RunAt<Frame>(dialogHandler) {
+			@Override
+			protected void runAt() {
 				log.info("executed");
-				tree.setSelectionPath(treePath);
-				tree.makeVisible(treePath);
-				assert tree.isVisible(treePath);
-			}
-		};
+				jtree.setSelectionPath(treePath);
+				jtree.makeVisible(treePath);
+				assert jtree.isVisible(treePath);
+			}
+		});
 
 	}
@@ -422,34 +393,32 @@
 
 	@Override
+	protected void joinableStart() {
+		super.joinableStart();
+		Dispatching.use(trees, this);
+	}
+
+	@Override
 	protected void joinableInterrupt() {
-		assert isActive();
+		Dispatching.drop(trees, this);
 		super.joinableInterrupt();
-
-		dispatch(new RunAt<Frame>() {
-			@Override
-			public void run() {
-				finish();
-			}
-		});
 	}
 
 	@Override
 	protected void joinableFinish() {
-		assert isActive();
-		log.debug("disposing frame " + this);
-		swing.dispose();
-	}
-
-	// @Override
-	// public boolean isDone() {
-	//	return super.isDone() && !swing.isDisplayable();
-	// }
-
-
-	@Override
-	public String getName() {
-		return title;
-	}
-
+		super.joinableFinish();
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.join(trees);
+		super.joinableJoin();
+	}
+
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		if (joinable == trees) {
+			proceedToState(state);
+		}
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/gui/FrameJoinable.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/FrameJoinable.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/FrameJoinable.java	(revision 97)
@@ -0,0 +1,148 @@
+package com.framsticks.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.swing.JFrame;
+import javax.swing.UIManager;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+
+public abstract class FrameJoinable extends SwingJoinable<JFrame> implements ExceptionResultHandler {
+	private static final Logger log =
+		Logger.getLogger(FrameJoinable.class);
+
+	protected String title;
+
+	protected final StatusBar statusBar;
+
+
+	/**
+	 *
+	 */
+	public FrameJoinable() {
+		statusBar = new StatusBar();
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+		if (hasSwing()) {
+			getSwing().setTitle(title);
+		}
+	}
+
+	/**
+	 * @return the statusBar
+	 */
+	public StatusBar getStatusBar() {
+		return statusBar;
+	}
+
+	@Override
+	public String getName() {
+		return title;
+	}
+
+	private final static AtomicBoolean sentGuiInitialization = new AtomicBoolean(false);
+
+
+	@Override
+	protected void joinableStart() {
+
+		if (sentGuiInitialization.compareAndSet(false, true)) {
+			dispatch(new RunAt<FrameJoinable>(ThrowExceptionHandler.getInstance()) {
+				@Override
+				protected void runAt() {
+					try {
+						boolean found = false;
+						// for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
+						//	log.info("look and feel available: " + info.getName());
+						//	if ("Nimbus".equals(info.getName())) {
+						//		UIManager.setLookAndFeel(info.getClassName());
+						//		found = true;
+						//		break;
+						//	}
+						// }
+						if (!found) {
+							UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+						}
+						JFrame.setDefaultLookAndFeelDecorated(true);
+					} catch (Exception e) {
+						throw new FramsticksException().msg("failed to initialize Look&Feel").cause(e);
+					}
+				}
+			});
+		}
+
+		super.joinableStart();
+		dispatch(new RunAt<FrameJoinable>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				getSwing().setVisible(true);
+			}
+		});
+
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		super.joinableInterrupt();
+
+		dispatch(new RunAt<Frame>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				finish();
+			}
+		});
+
+	}
+
+	@Override
+	protected void joinableFinish() {
+		super.joinableFinish();
+		log.debug("disposing frame " + this);
+		getSwing().dispose();
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		super.joinableJoin();
+
+	}
+
+	@Override
+	protected void initializeGui() {
+		setSwing(new JFrame(title));
+		statusBar.initializeGui();
+
+		Container contentPane = getSwing().getContentPane();
+		contentPane.setLayout(new BorderLayout());
+		contentPane.add(statusBar.getSwing(), BorderLayout.SOUTH);
+
+		getSwing().setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+
+		getSwing().addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowClosing(WindowEvent e) {
+				log.info("received closing");
+				interrupt();
+			}
+		});
+
+
+	}
+
+	@Override
+	public void handle(FramsticksException exception) {
+		statusBar.handle(exception);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/Gui.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Gui.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/Gui.java	(revision 97)
@@ -45,8 +45,14 @@
 
 	public static Control createComponentForText(PrimitiveParam<?> valueParam) {
-		if (valueParam.getMin(Object.class) != null) {
-			return new TextAreaControl(valueParam);
+		if (valueParam.getMax(Object.class) != null) {
+			return new TextFieldControl(valueParam);
 		}
-		return new TextFieldControl(valueParam);
+		return new TextAreaControl(valueParam);
+
+
+		// if (valueParam.getMin(Object.class) != null) {
+		// 	return new TextAreaControl(valueParam);
+		// }
+		// return new TextFieldControl(valueParam);
 	}
 
@@ -64,5 +70,5 @@
 				return new SliderControl(decimalParam);
 			}
-			return createComponentForText(decimalParam);
+			return new TextFieldControl(decimalParam);
 		}
 		if (param instanceof FloatParam) {
@@ -71,23 +77,23 @@
 				return new SliderControl(floatParam);
 			}
-			return createComponentForText(floatParam);
+			return new TextFieldControl(floatParam);
 		}
 		if (param instanceof StringParam) {
-			return createComponentForText((StringParam)param);
+			return createComponentForText((StringParam) param);
 		}
 		if (param instanceof ProcedureParam) {
-			return new ProcedureControl((ProcedureParam)param);
+			return new ProcedureControl((ProcedureParam) param);
 		}
 		if (param instanceof BinaryParam) {
-			return createComponentForText((BinaryParam)param);
+			return new TextFieldControl((BinaryParam) param);
 		}
 		if (param instanceof ColorParam) {
-			return createComponentForText((ColorParam) param);
+			return new TextFieldControl((ColorParam) param);
 		}
 		if (param instanceof UniversalParam) {
-			return new TextAreaControl((UniversalParam)param);
+			return new TextAreaControl((UniversalParam) param);
 		}
 		if (param instanceof EventParam) {
-			return new EventControl((EventParam)param);
+			return new EventControl((EventParam) param);
 		}
 		return null;
Index: java/main/src/main/java/com/framsticks/gui/InstanceAtFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/InstanceAtFrame.java	(revision 96)
+++ 	(revision )
@@ -1,179 +1,0 @@
-package com.framsticks.gui;
-
-import org.apache.log4j.Logger;
-
-import com.framsticks.core.Instance;
-import com.framsticks.core.InstanceListener;
-import com.framsticks.core.ListChange;
-import com.framsticks.core.Node;
-import com.framsticks.core.Path;
-import com.framsticks.params.CompositeParam;
-import com.framsticks.params.FramsClass;
-
-import java.util.*;
-
-import javax.swing.tree.TreePath;
-import com.framsticks.util.dispatching.RunAt;
-
-/**
- * @author Piotr Sniegowski
- */
-public class InstanceAtFrame implements InstanceListener {
-
-	private static final Logger log = Logger.getLogger(InstanceAtFrame.class);
-
-	protected final Frame frame;
-	protected final Instance instance;
-	protected final Map<String, Panel> knownPanels = new HashMap<String, Panel>();
-	protected TreeNode rootTreeNode;
-
-	public InstanceAtFrame(Instance instance, Frame frame) {
-		this.frame = frame;
-		this.instance = instance;
-	}
-
-	public Frame getFrame() {
-		return frame;
-	}
-
-	/**
-	 * @return the instance
-	 */
-	public Instance getInstance() {
-		return instance;
-	}
-
-	public void registerPanel(Panel panel) {
-	}
-
-	public Panel findPanel(String accessId) {
-		assert frame.isActive();
-		return (knownPanels.containsKey(accessId) ? knownPanels.get(accessId) : null);
-	}
-
-	public final String getName() {
-		return instance.getName();
-	}
-
-	public Panel preparePanel(CompositeParam param, FramsClass framsClass) {
-		assert frame.isActive();
-		Panel panel = preparePanelImpl(param, framsClass);
-		assert panel != null;
-		String accessId = param.computeAccessId();
-		panel.uniqueName = accessId + "@" + instance.getName();
-		knownPanels.put(accessId, panel);
-		frame.cardPanel.add(panel, panel.uniqueName);
-		log.debug("prepared panel for " + panel);
-		return panel;
-	}
-
-	protected Panel preparePanelImpl(CompositeParam param, FramsClass framsClass) {
-		assert frame.isActive();
-		List<Panel> panels = new ArrayList<Panel>();
-
-		Panel.Parameters parameters = new Panel.Parameters(this, param, framsClass);
-		for (PanelProvider pp : frame.browser.panelProviders) {
-			Panel p = pp.providePanel(parameters);
-			if (p != null) {
-				panels.add(p);
-			}
-		}
-
-		if (panels.isEmpty()) {
-			return new EmptyPanel(parameters);
-		}
-		if (panels.size() == 1) {
-			return panels.get(0);
-		}
-		return new MultiPanel(parameters, panels);
-
-	}
-
-	@Override
-	public void onListChange(Path path, ListChange change) {
-
-	}
-
-	public TreePath getTreePath(Path path, boolean create) {
-		assert frame.isActive();
-		TreeNode t = rootTreeNode;
-		TreePath result = new TreePath(frame.rootNode).pathByAddingChild(rootTreeNode);
-		List<Node> nodes = path.getNodes();
-		Iterator<Node> i = nodes.iterator();
-		i.next();
-		// Node first = i.next();
-
-		// if (!t.path.isResolved()) {
-		//	t.path = new Path(path.getInstance(), nodes, first);
-		// }
-		while (i.hasNext()) {
-			Node n = i.next();
-			TreeNode r = null;
-			for (TreeNode c : t.childrenIterable()) {
-				if (c.paramId.equals(n.getParam().getId())) {
-					r = c;
-					break;
-				}
-			}
-			if (r == null) {
-				log.debug("missing " + n.getParam().getId() + " in " + t);
-				if (!create) {
-					return result;
-				}
-				Path p = Path.build().instance(path.getInstance()).buildUpTo(nodes, n).finish();
-
-
-				log.debug("forced resolution: creating treenode for " + p);
-				TreeNode childNode = new TreeNode(InstanceAtFrame.this, p);
-
-				frame.addNode(childNode, t);
-				// frame.treeModel.reload();
-				// t.add(childNode);
-				// frame.treeModel.nodeStructureChanged(t);
-
-				r = childNode;
-			} else {
-				// if (!r.path.isResolved()) {
-				//	r.path = new Path(path.getInstance(), nodes, n);
-				// }
-			}
-			result = result.pathByAddingChild(r);
-			t = r;
-		}
-		return result;
-	}
-
-	@Override
-	public void onFetch(final Path path) {
-		assert instance.isActive();
-		log.trace("fetched " + path);
-
-		frame.dispatch(new RunAt<Frame>() {
-			@Override
-			public void run() {
-
-				TreePath treePath = getTreePath(path, true);
-				assert treePath.getPathCount() == path.size() + 1;
-
-				final TreeNode result = (TreeNode) treePath.getLastPathComponent();
-				// log.trace("found " + result + " == " + path);
-				instance.dispatch(new RunAt<Instance>() {
-					@Override
-					public void run() {
-						result.reactForFetchResult(path, null);
-					}
-				});
-			}
-		});
-	}
-
-	@Override
-	public void onRun(Exception e) {
-
-	}
-
-	@Override
-	public void onStop(Exception e) {
-
-	}
-}
Index: java/main/src/main/java/com/framsticks/gui/MainFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/MainFrame.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/MainFrame.java	(revision 97)
@@ -1,16 +1,17 @@
 package com.framsticks.gui;
 
-import com.framsticks.gui.windows.console.ConsoleFrame;
-import com.framsticks.util.swing.MenuConstructor;
-import org.apache.log4j.Logger;
-
-import javax.swing.*;
-import javax.swing.border.TitledBorder;
-import java.awt.*;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.KeyStroke;
+import javax.swing.WindowConstants;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.util.swing.MenuConstructor;
 
 /**
@@ -28,5 +29,6 @@
 	 */
 	public MainFrame(final Browser browser) {
-		super("framsticks", browser);
+		super(browser);
+		setTitle("framsticks");
 		log.debug("creating main frame");
 
@@ -35,6 +37,6 @@
 
 	@Override
-	public void configure() {
-		super.configure();
+	protected void initializeGui() {
+		super.initializeGui();
 
 		new MenuConstructor(fileMenu)
@@ -42,5 +44,5 @@
 				@Override
 				public void actionPerformed(ActionEvent actionEvent) {
-					showConsoleFrame();
+					// showConsoleFrame();
 				}
 			})
@@ -145,86 +147,75 @@
 	// }
 
-	public void setSimulationRunning(final boolean run) {
-		assert isActive();
-		/*
-		remoteInstance.invokeLater(new Runnable() {
-			@Override
-			public void run() {
-				remoteInstance.setRunning(run);
-			}
-		});
-		*/
-	}
-
-	/**
-	 * Creates panel with start, step, stop buttons.
-	 */
-	@Override
-	protected JPanel createLeftTopPanel() {
-		assert isActive();
-		Dimension buttonDimension = new Dimension(45, 45);
-
-		JPanel panel = new JPanel();
-
-		stop = new JButton(ImageProvider.loadImage(ImageProvider.SIM_STOP));
-		stop.addActionListener(new ActionListener() {
-
-			public void actionPerformed(ActionEvent e) {
-				setSimulationRunning(false);
-			}
-
-		});
-
-		stop.setPreferredSize(buttonDimension);
-		stop.setToolTipText("Simulation Stop");
-		stop.setEnabled(false);
-
-		step = new JButton(ImageProvider.loadImage(ImageProvider.SIM_STEP));
-		/*
-		step.addActionListener(new ActionListener() {
-
-			public void actionPerformed(ActionEvent e) {
-				connection.send(new CallQuery().setMethod("step").setPath("/simulator"));
-			}
-
-		});
-		*/
-
-		step.setPreferredSize(buttonDimension);
-		step.setToolTipText("Simulation Step");
-
-		start = new JButton(ImageProvider.loadImage(ImageProvider.SIM_START));
-		start.addActionListener(new ActionListener() {
-
-			public void actionPerformed(ActionEvent e) {
-				setSimulationRunning(true);
-			}
-
-		});
-
-		start.setPreferredSize(buttonDimension);
-		start.setToolTipText("Start Simulation");
-
-		JPanel buttonPanel = new JPanel();
-		buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
-		buttonPanel.add(Box.createHorizontalStrut(5));
-		buttonPanel.add(stop);
-		buttonPanel.add(Box.createHorizontalStrut(10));
-		buttonPanel.add(step);
-		buttonPanel.add(Box.createHorizontalStrut(10));
-		buttonPanel.add(start);
-		buttonPanel.add(Box.createHorizontalStrut(5));
-
-		buttonPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
-				.createRaisedBevelBorder(), "Simulation Control",
-				TitledBorder.CENTER, TitledBorder.DEFAULT_POSITION
-				));
-
-		panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
-		panel.add(Box.createHorizontalGlue());
-		panel.add(buttonPanel);
-		panel.add(Box.createHorizontalGlue());
-		return panel;
-	}
+
+	// /**
+	//  * Creates panel with start, step, stop buttons.
+	//  */
+	// @Override
+	// protected JPanel createLeftTopPanel() {
+	// 	assert isActive();
+	// 	Dimension buttonDimension = new Dimension(45, 45);
+
+	// 	JPanel panel = new JPanel();
+
+	// 	stop = new JButton(ImageProvider.loadImage(ImageProvider.SIM_STOP));
+	// 	stop.addActionListener(new ActionListener() {
+
+	// 		public void actionPerformed(ActionEvent e) {
+	// 			setSimulationRunning(false);
+	// 		}
+
+	// 	});
+
+	// 	stop.setPreferredSize(buttonDimension);
+	// 	stop.setToolTipText("Simulation Stop");
+	// 	stop.setEnabled(false);
+
+	// 	step = new JButton(ImageProvider.loadImage(ImageProvider.SIM_STEP));
+	// 	/*
+	// 	step.addActionListener(new ActionListener() {
+
+	// 		public void actionPerformed(ActionEvent e) {
+	// 			connection.send(new CallQuery().setMethod("step").setPath("/simulator"));
+	// 		}
+
+	// 	});
+	// 	*/
+
+	// 	step.setPreferredSize(buttonDimension);
+	// 	step.setToolTipText("Simulation Step");
+
+	// 	start = new JButton(ImageProvider.loadImage(ImageProvider.SIM_START));
+	// 	start.addActionListener(new ActionListener() {
+
+	// 		public void actionPerformed(ActionEvent e) {
+	// 			setSimulationRunning(true);
+	// 		}
+
+	// 	});
+
+	// 	start.setPreferredSize(buttonDimension);
+	// 	start.setToolTipText("Start Simulation");
+
+	// 	JPanel buttonPanel = new JPanel();
+	// 	buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
+	// 	buttonPanel.add(Box.createHorizontalStrut(5));
+	// 	buttonPanel.add(stop);
+	// 	buttonPanel.add(Box.createHorizontalStrut(10));
+	// 	buttonPanel.add(step);
+	// 	buttonPanel.add(Box.createHorizontalStrut(10));
+	// 	buttonPanel.add(start);
+	// 	buttonPanel.add(Box.createHorizontalStrut(5));
+
+	// 	buttonPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
+	// 			.createRaisedBevelBorder(), "Simulation Control",
+	// 			TitledBorder.CENTER, TitledBorder.DEFAULT_POSITION
+	// 			));
+
+	// 	panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
+	// 	panel.add(Box.createHorizontalGlue());
+	// 	panel.add(buttonPanel);
+	// 	panel.add(Box.createHorizontalGlue());
+	// 	return panel;
+	// }
 
 	/**
@@ -233,14 +224,14 @@
 	private void setFrameProperties() {
 		assert isActive();
-		swing.setMinimumSize(swing.getPreferredSize());
-		swing.setSize(swing.getPreferredSize());
-		swing.setMaximumSize(screenDimension);
-		swing.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
-
-		swing.setIconImage(ImageProvider.loadImage(ImageProvider.LOGO)
+		getSwing().setMinimumSize(getSwing().getPreferredSize());
+		getSwing().setSize(getSwing().getPreferredSize());
+		getSwing().setMaximumSize(screenDimension);
+		getSwing().setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+		getSwing().setIconImage(ImageProvider.loadImage(ImageProvider.LOGO)
 				.getImage());
 
 
-		swing.addWindowListener(new WindowAdapter() {
+		getSwing().addWindowListener(new WindowAdapter() {
 			public void windowClosing(WindowEvent e) {
 				assert isActive();
@@ -251,18 +242,18 @@
 				*/
 				onWindowClosing();
-				swing.dispose();
+				getSwing().dispose();
 			}
 		});
 	}
 
-	public ConsoleFrame showConsoleFrame() {
-		assert isActive();
-		/*
-		ConsoleFrame consoleFrame = new ConsoleFrame(connection);
-		consoleFrame.show(MainFrame.this);
-		return consoleFrame;
-		*/
-		return null;
-	}
+	// public ConsoleFrame showConsoleFrame() {
+	// 	assert isActive();
+	// 	/*
+	// 	ConsoleFrame consoleFrame = new ConsoleFrame(connection);
+	// 	consoleFrame.show(MainFrame.this);
+	// 	return consoleFrame;
+	// 	*/
+	// 	return null;
+	// }
 
 	/**
@@ -271,8 +262,7 @@
 	private void disconnect() {
 		assert isActive();
-		//remoteInstance.disconnect();
 		browser.clear();
 		onWindowClosing();
-		statusBar.setText("You are disconnected");
+		// statusBar.setText("You are disconnected");
 	}
 
Index: java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java	(revision 97)
@@ -39,4 +39,6 @@
 
 		applyButton = new JButton("Apply");
+		applyButton.setName("apply");
+
 		applyButton.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
Index: java/main/src/main/java/com/framsticks/gui/MultiPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/MultiPanel.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/MultiPanel.java	(revision 97)
@@ -24,5 +24,5 @@
 		for (Panel p : panels) {
 			assert p.getClassName().equals(getClassName());
-			assert p.getInstanceAtFrame() == getInstanceAtFrame();
+			assert p.getTreeAtFrame() == getTreeAtFrame();
 			tabbedPane.add(p.getTitle(), p);
 		}
Index: java/main/src/main/java/com/framsticks/gui/ObjectPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ObjectPanel.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/ObjectPanel.java	(revision 97)
@@ -17,4 +17,6 @@
 import java.util.Map;
 import static com.framsticks.util.lang.Containers.filterInstanceof;
+
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.dispatching.RunAt;
 
@@ -70,5 +72,5 @@
 	public void pullValuesFromLocalToUser(AccessInterface access) {
 		assert currentTreeNode != null;
-		assert currentTreeNode.path.getInstance().isActive();
+		assert currentTreeNode.path.getTree().isActive();
 		log.debug("refreshing components");
 
@@ -78,7 +80,7 @@
 		}
 
-		frame.dispatch(new RunAt<Frame>() {
+		frame.dispatch(new RunAt<Frame>(frame) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				if (currentTreeNode.localChanges != null) {
 					for (Map.Entry<ValueControl, Object> e : currentTreeNode.localChanges.entrySet()) {
@@ -111,4 +113,9 @@
 	}
 
+	@Override
+	public void handle(FramsticksException exception) {
+		frame.handle(exception);
+	}
+
 	// public void updateValue() {
 	//	//assert panel.getFrame().isActive();
Index: java/main/src/main/java/com/framsticks/gui/Panel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Panel.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/Panel.java	(revision 97)
@@ -15,10 +15,10 @@
 
 	public static class Parameters {
-		public final InstanceAtFrame instanceAtFrame;
+		public final TreeAtFrame treeAtFrame;
 		public final CompositeParam param;
 		public final FramsClass framsClass;
 
-		public Parameters(InstanceAtFrame instanceAtFrame, CompositeParam param, FramsClass framsClass) {
-			this.instanceAtFrame = instanceAtFrame;
+		public Parameters(TreeAtFrame treeAtFrame, CompositeParam param, FramsClass framsClass) {
+			this.treeAtFrame = treeAtFrame;
 			this.param = param;
 			this.framsClass = framsClass;
@@ -29,5 +29,5 @@
 
 	protected TreeNode currentTreeNode;
-	protected final InstanceAtFrame instanceAtFrame;
+	protected final TreeAtFrame treeAtFrame;
 	protected final Frame frame;
 	protected final String className;
@@ -37,6 +37,6 @@
 
 	public Panel(Parameters parameters) {
-		this.instanceAtFrame = parameters.instanceAtFrame;
-		this.frame = parameters.instanceAtFrame.getFrame();
+		this.treeAtFrame = parameters.treeAtFrame;
+		this.frame = parameters.treeAtFrame.getFrame();
 		this.framsClass = parameters.framsClass;
 		this.param = parameters.param;
@@ -57,6 +57,6 @@
 	}
 
-	public final InstanceAtFrame getInstanceAtFrame() {
-		return instanceAtFrame;
+	public final TreeAtFrame getTreeAtFrame() {
+		return treeAtFrame;
 	}
 
Index: java/main/src/main/java/com/framsticks/gui/PopupMenuEntryProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/PopupMenuEntryProvider.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/PopupMenuEntryProvider.java	(revision 97)
@@ -0,0 +1,9 @@
+package com.framsticks.gui;
+
+import javax.swing.JPopupMenu;
+
+import com.framsticks.core.Path;
+
+public interface PopupMenuEntryProvider {
+	public void provide(JPopupMenu menu, Path path);
+}
Index: java/main/src/main/java/com/framsticks/gui/StatusBar.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/StatusBar.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/StatusBar.java	(revision 97)
@@ -0,0 +1,72 @@
+package com.framsticks.gui;
+
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+// import java.awt.Dimension;
+
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.gui.controls.Control;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.RunAt;
+
+public class StatusBar implements ExceptionResultHandler, Dispatcher<StatusBar> {
+	private static final Logger log = Logger.getLogger(StatusBar.class);
+
+	protected JTextField statusBar;
+	protected JPanel swing;
+
+	/**
+	 *
+	 */
+	public StatusBar() {
+	}
+
+	@Override
+	public void handle(final FramsticksException exception) {
+		dispatch(new RunAt<StatusBar>(this) {
+
+			@Override
+			protected void runAt() {
+				log.error("error: " + exception);
+				statusBar.setText(exception.getShortMessage(new StringBuilder()).toString());
+			}
+		});
+	}
+
+	public void initializeGui() {
+		statusBar = new JTextField();
+		statusBar.setEditable(false);
+
+		swing = new JPanel();
+		swing.setMaximumSize(new Dimension(Integer.MAX_VALUE, Control.LINE_HEIGHT));
+
+		swing.setLayout(new BorderLayout());
+		swing.add(statusBar, BorderLayout.CENTER);
+		// swing.add(statusBar);
+	}
+
+	@Override
+	public boolean isActive() {
+		return SwingDispatcher.getInstance().isActive();
+	}
+
+	@Override
+	public void dispatch(RunAt<? extends StatusBar> runnable) {
+		SwingDispatcher.getInstance().dispatch(runnable);
+	}
+
+	/**
+	 * @return the swing
+	 */
+	public JPanel getSwing() {
+		return swing;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/SwingDispatcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/SwingDispatcher.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/SwingDispatcher.java	(revision 97)
@@ -3,4 +3,5 @@
 import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.dispatching.Task;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
 
 import javax.swing.*;
@@ -21,7 +22,7 @@
 
 	public SwingDispatcher() {
-		dispatch(new RunAt<C>() {
+		dispatch(new RunAt<C>(ThrowExceptionHandler.getInstance()) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				Thread.currentThread().setName("gui");
 			}
Index: java/main/src/main/java/com/framsticks/gui/SwingJoinable.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/SwingJoinable.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/SwingJoinable.java	(revision 97)
@@ -0,0 +1,73 @@
+package com.framsticks.gui;
+
+
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.AbstractJoinable;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+
+public abstract class SwingJoinable<Swing> extends AbstractJoinable implements Dispatcher<SwingJoinable<Swing>> {
+
+	private Swing swing;
+
+	/**
+	 * @return the swing
+	 */
+	public Swing getSwing() {
+		if (swing == null) {
+			throw new FramsticksException().msg("swing has not yet been initialized").arg("in", this);
+		}
+		return swing;
+	}
+
+	public boolean hasSwing() {
+		return swing != null;
+	}
+
+	/**
+	 * @param swing the swing to set
+	 */
+	protected void setSwing(Swing swing) {
+		this.swing = swing;
+	}
+
+
+	protected abstract void initializeGui();
+
+	@Override
+	protected void joinableStart() {
+		dispatch(new RunAt<SwingJoinable<Swing>>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				initializeGui();
+			}
+		});
+	}
+
+	@Override
+	public boolean isActive() {
+		return SwingDispatcher.instance.isActive();
+	}
+
+	@Override
+	public void dispatch(RunAt<? extends SwingJoinable<Swing>> runnable) {
+		SwingDispatcher.getInstance().dispatch(runnable);
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+
+	}
+
+	@Override
+	protected void joinableFinish() {
+
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/TreeAtFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/TreeAtFrame.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/TreeAtFrame.java	(revision 97)
@@ -0,0 +1,179 @@
+package com.framsticks.gui;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.core.Tree;
+import com.framsticks.core.TreeListener;
+import com.framsticks.core.ListChange;
+import com.framsticks.core.Node;
+import com.framsticks.core.Path;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
+
+import java.util.*;
+
+import javax.swing.tree.TreePath;
+import com.framsticks.util.dispatching.RunAt;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class TreeAtFrame implements TreeListener {
+
+	private static final Logger log = Logger.getLogger(TreeAtFrame.class);
+
+	protected final Frame frame;
+	protected final Tree tree;
+	protected final Map<String, Panel> knownPanels = new HashMap<String, Panel>();
+	protected TreeNode rootTreeNode;
+
+	public TreeAtFrame(Tree tree, Frame frame) {
+		this.frame = frame;
+		this.tree = tree;
+	}
+
+	public Frame getFrame() {
+		return frame;
+	}
+
+	/**
+	 * @return the tree
+	 */
+	public Tree getTree() {
+		return tree;
+	}
+
+	public void registerPanel(Panel panel) {
+	}
+
+	public Panel findPanel(String accessId) {
+		assert frame.isActive();
+		return (knownPanels.containsKey(accessId) ? knownPanels.get(accessId) : null);
+	}
+
+	public final String getName() {
+		return tree.getName();
+	}
+
+	public Panel preparePanel(CompositeParam param, FramsClass framsClass) {
+		assert frame.isActive();
+		Panel panel = preparePanelImpl(param, framsClass);
+		assert panel != null;
+		String accessId = param.computeAccessId();
+		panel.uniqueName = accessId + "@" + tree.getName();
+		knownPanels.put(accessId, panel);
+		frame.cardPanel.add(panel, panel.uniqueName);
+		log.debug("prepared panel for " + panel);
+		return panel;
+	}
+
+	protected Panel preparePanelImpl(CompositeParam param, FramsClass framsClass) {
+		assert frame.isActive();
+		List<Panel> panels = new ArrayList<Panel>();
+
+		Panel.Parameters parameters = new Panel.Parameters(this, param, framsClass);
+		for (PanelProvider pp : frame.browser.panelProviders) {
+			Panel p = pp.providePanel(parameters);
+			if (p != null) {
+				panels.add(p);
+			}
+		}
+
+		if (panels.isEmpty()) {
+			return new EmptyPanel(parameters);
+		}
+		if (panels.size() == 1) {
+			return panels.get(0);
+		}
+		return new MultiPanel(parameters, panels);
+
+	}
+
+	@Override
+	public void onListChange(Path path, ListChange change) {
+
+	}
+
+	public TreePath getTreePath(Path path, boolean create) {
+		assert frame.isActive();
+		TreeNode t = rootTreeNode;
+		TreePath result = new TreePath(frame.rootNode).pathByAddingChild(rootTreeNode);
+		List<Node> nodes = path.getNodes();
+		Iterator<Node> i = nodes.iterator();
+		i.next();
+		// Node first = i.next();
+
+		// if (!t.path.isResolved()) {
+		//	t.path = new Path(path.getInstance(), nodes, first);
+		// }
+		while (i.hasNext()) {
+			Node n = i.next();
+			TreeNode r = null;
+			for (TreeNode c : t.childrenIterable()) {
+				if (c.param.getId().equals(n.getParam().getId())) {
+					r = c;
+					break;
+				}
+			}
+			if (r == null) {
+				log.debug("missing " + n.getParam().getId() + " in " + t);
+				if (!create) {
+					return result;
+				}
+				Path p = Path.build().tree(path.getTree()).buildUpTo(nodes, n).finish();
+
+
+				log.debug("forced resolution: creating treenode for " + p);
+				TreeNode childNode = new TreeNode(TreeAtFrame.this, p);
+
+				frame.addNode(childNode, t);
+				// frame.treeModel.reload();
+				// t.add(childNode);
+				// frame.treeModel.nodeStructureChanged(t);
+
+				r = childNode;
+			} else {
+				// if (!r.path.isResolved()) {
+				//	r.path = new Path(path.getInstance(), nodes, n);
+				// }
+			}
+			result = result.pathByAddingChild(r);
+			t = r;
+		}
+		return result;
+	}
+
+	@Override
+	public void onFetch(final Path path) {
+		assert tree.isActive();
+		log.trace("fetched " + path);
+
+		frame.dispatch(new RunAt<Frame>(frame) {
+			@Override
+			protected void runAt() {
+
+				TreePath treePath = getTreePath(path, true);
+				assert treePath.getPathCount() == path.size() + 1;
+
+				final TreeNode result = (TreeNode) treePath.getLastPathComponent();
+				// log.trace("found " + result + " == " + path);
+				tree.dispatch(new RunAt<Tree>(frame) {
+					@Override
+					protected void runAt() {
+						result.reactForFetchResult(path, null);
+					}
+				});
+			}
+		});
+	}
+
+	@Override
+	public void onRun(Exception e) {
+
+	}
+
+	@Override
+	public void onStop(Exception e) {
+
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/TreeNode.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/TreeNode.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/TreeNode.java	(revision 97)
@@ -1,9 +1,9 @@
 package com.framsticks.gui;
 
-import com.framsticks.communication.Connection;
 import com.framsticks.communication.Subscription;
 import com.framsticks.communication.util.LoggingStateCallback;
-import com.framsticks.core.Instance;
-import com.framsticks.core.InstanceUtils;
+import com.framsticks.core.Mode;
+import com.framsticks.core.Tree;
+import com.framsticks.core.TreeOperations;
 import com.framsticks.core.ListChange;
 import com.framsticks.core.Path;
@@ -18,6 +18,7 @@
 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.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.Logging;
 import org.apache.log4j.Logger;
@@ -31,5 +32,5 @@
 import static com.framsticks.util.lang.Containers.filterInstanceof;
 import com.framsticks.util.swing.TreeNodeUtils;
-import static com.framsticks.core.InstanceUtils.*;
+import static com.framsticks.core.TreeOperations.*;
 
 /**
@@ -37,5 +38,5 @@
  */
 @SuppressWarnings("serial")
-public class TreeNode extends DefaultMutableTreeNode implements NodeListener {
+public class TreeNode extends DefaultMutableTreeNode implements NodeListener, ExceptionResultHandler {
 
 	private static final Logger log = Logger.getLogger(TreeNode.class.getName());
@@ -44,5 +45,5 @@
 
 	final protected Frame frame;
-	final protected InstanceAtFrame instanceAtFrame;
+	final protected TreeAtFrame treeAtFrame;
 
 	final protected Map<EventParam, Subscription<?>> userSubscriptions = new HashMap<>();
@@ -50,22 +51,22 @@
 	protected String tooltip;
 	protected String name;
-	protected final String paramId;
+	protected final CompositeParam param;
 	protected String iconName;
 	protected Path path;
 
-	public TreeNode(InstanceAtFrame instanceAtFrame, final Path path) {
-		this.frame = instanceAtFrame.getFrame();
-		assert frame.isActive();
-		this.paramId = path.getLastElement();
-		this.name = this.paramId;
+	public TreeNode(TreeAtFrame treeAtFrame, final Path path) {
+		this.frame = treeAtFrame.getFrame();
+		assert frame.isActive();
+		this.param = path.getTop().getParam();
+		this.name = this.param.getId();
 		log.debug("creating treenode " + name + ": " + path);
 		this.path = path;
-		this.instanceAtFrame = instanceAtFrame;
+		this.treeAtFrame = treeAtFrame;
 
 		iconName = TreeCellRenderer.findIconName(name, path.getTextual());
 		tooltip = "?";
-		path.getInstance().dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
+		path.getTree().dispatch(new RunAt<Tree>(this) {
+			@Override
+			protected void runAt() {
 				updateDescriptions(path);
 			}
@@ -74,10 +75,10 @@
 
 	public void fetch(final Path p) {
-		assert p.getInstance().isActive();
+		assert p.getTree().isActive();
 		log.debug("fetching: " + p);
-		p.getInstance().fetchValues(p, new AbstractStateFunctor() {
-			@Override
-			public void call() {
-				// reactForFetchResult(p, e);
+		p.getTree().get(p, Mode.FETCH, new FutureHandler<Object>(this) {
+			@Override
+			protected void result(Object result) {
+
 			}
 		});
@@ -85,9 +86,9 @@
 
 	protected void reactForFetchResult(final Path p, Exception e) {
-		assert p.getInstance().isActive();
+		assert p.getTree().isActive();
 		if (Logging.log(log, "fetch", TreeNode.this, e)) {
-			frame.dispatch(new RunAt<Frame>() {
+			frame.dispatch(new RunAt<Frame>(this) {
 				@Override
-				public void run() {
+				protected void runAt() {
 					log.debug("removing node from tree: " + p);
 					frame.treeModel.removeNodeFromParent(TreeNode.this);
@@ -97,7 +98,7 @@
 		}
 		updateChildren(p);
-		frame.dispatch(new RunAt<Frame>() {
-			@Override
-			public void run() {
+		frame.dispatch(new RunAt<Frame>(this) {
+			@Override
+			protected void runAt() {
 				//TODO maybe this should be called from some better place
 				useOrCreatePanel();
@@ -109,7 +110,7 @@
 		assert !frame.isActive();
 		/** TODO those two actions could be merged into single closure */
-		frame.dispatch(new RunAt<Frame>() {
-			@Override
-			public void run() {
+		frame.dispatch(new RunAt<Frame>(this) {
+			@Override
+			protected void runAt() {
 				updatePath(newPath);
 			}
@@ -140,10 +141,7 @@
 	 */
 	protected void updateChildren(final Path p) {
-		assert p.getInstance().isActive();
+		assert p.getTree().isActive();
 		log.debug("updating children of " + this);
-		AccessInterface access = InstanceUtils.bindAccess(p.getInstance(), p.getTop());
-		if (access == null) {
-			return;
-		}
+		AccessInterface access = TreeOperations.bindAccess(p.getTree(), p.getTop());
 		final List<Path> childrenPaths = new LinkedList<Path>();
 		/**Prepare path for each child.*/
@@ -154,7 +152,7 @@
 		/**If some child were found, update in frame context.*/
 		if (childrenPaths.size() > 0) {
-			frame.dispatch(new RunAt<Frame>() {
+			frame.dispatch(new RunAt<Frame>(this) {
 				@Override
-				public void run() {
+				protected void runAt() {
 					// TreePath treePath = frame.startChange();
 					updatePath(p);
@@ -173,5 +171,5 @@
 						}
 						log.debug("update: treenode for " + p);
-						TreeNode childNode = new TreeNode(instanceAtFrame, childPath);
+						TreeNode childNode = new TreeNode(treeAtFrame, childPath);
 
 						frame.addNode(childNode, TreeNode.this);
@@ -191,7 +189,7 @@
 		final Path p = path;
 
-		p.getInstance().dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
+		p.getTree().dispatch(new RunAt<Tree>(this) {
+			@Override
+			protected void runAt() {
 				final Path updated = (p.isResolved()) ? p : p.tryFindResolution();
 				if (updated.isResolved()) {
@@ -201,5 +199,5 @@
 					return;
 				}
-				p.getInstance().resolve(updated, new Future<Path>(Logging.logger(log, "resolve and select", TreeNode.this)) {
+				p.getTree().resolve(updated, new FutureHandler<Path>(Logging.logger(log, "resolve and select", TreeNode.this)) {
 					@Override
 					protected void result(Path result) {
@@ -224,27 +222,19 @@
 
 	protected void updateDescriptions(Path p) {
-		assert p.getInstance().isActive();
+		assert p.getTree().isActive();
 
 		if (!p.isResolved()) {
 			return;
 		}
-		AccessInterface access = InstanceUtils.bindAccess(p);
-
-		final String tooltip = new TooltipConstructor()
-			.append("frams", access.getId())
-			.append("java", p.getTopObject().getClass().getCanonicalName())
-			.append("access", access.getClass().getSimpleName())
-			.append("name", name)
-			.append("id", paramId)
-			.append("object", Integer.toHexString(System.identityHashCode(this)))
-			.build()
-			;
+		AccessInterface access = TreeOperations.bindAccess(p);
+
+		final String tooltip = new TooltipConstructor().append("frams", access.getId()).append("java", p.getTopObject().getClass().getCanonicalName()).append("access", access.getClass().getSimpleName()).append("name", name).append("id", param.getId()).append("object", Integer.toHexString(System.identityHashCode(this))).build();
 
 		StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name"));
 		final String name = (nameParam != null ? access.get(nameParam, String.class) : path.getTop().getParam().getId());
 
-		frame.dispatch(new RunAt<Frame>() {
-			@Override
-			public void run() {
+		frame.dispatch(new RunAt<Frame>(this) {
+			@Override
+			protected void runAt() {
 				TreeNode.this.tooltip = tooltip;
 				TreeNode.this.name = name;
@@ -254,36 +244,4 @@
 		});
 	}
-
-/*
-	public void updateData() {
-		assert browser.isActive();
-		final Node node = getNode();
-		browser.manager.invokeLater(new Runnable() {
-			@Override
-			public void run() {
-				node.fetchValues(new StateFunctor() {
-					@Override
-					public void call(Exception e) {
-						if (e != null) {
-							return;
-						}
-						browser.invokeLater(new Runnable() {
-							@Override
-							public void run() {
-								assert browser.isActive();
-								if (panel.getCurrentTreeNode() == TreeNode.this) {
-									panel.refreshComponents();
-								}
-
-								browser.tree.repaint();
-								panel.refreshComponents();
-							}
-						});
-					}
-				});
-			}
-		});
-	}
-*/
 
 	public void showPanel() {
@@ -301,13 +259,13 @@
 		assert p.isResolved();
 		panel.setCurrentTreeNode(this);
-		p.getInstance().dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				AccessInterface access = InstanceUtils.bindAccess(p);
+		p.getTree().dispatch(new RunAt<Tree>(this) {
+			@Override
+			protected void runAt() {
+				AccessInterface access = TreeOperations.bindAccess(p);
 				panel.pullValuesFromLocalToUser(access);
 
-				frame.dispatch(new RunAt<Frame>() {
+				frame.dispatch(new RunAt<Frame>(this) {
 					@Override
-					public void run() {
+					protected void runAt() {
 						showPanel();
 					}
@@ -331,5 +289,5 @@
 
 		CompositeParam param = path.getTop().getParam();
-		panel = instanceAtFrame.findPanel(param.computeAccessId());
+		panel = treeAtFrame.findPanel(param.computeAccessId());
 		if (panel != null) {
 			log.debug("found prepared panel for: " + path);
@@ -339,14 +297,14 @@
 		final Path p = path;
 		log.debug("preparing panel: " + p);
-		p.getInstance().dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				assert p.getInstance().isActive();
+		p.getTree().dispatch(new RunAt<Tree>(this) {
+			@Override
+			protected void runAt() {
+				assert p.getTree().isActive();
 				final CompositeParam param = p.getTop().getParam();
-				final FramsClass framsClass = p.getInstance().getInfoFromCache(param.getContainedTypeName());
-				frame.dispatch(new RunAt<Frame>() {
+				final FramsClass framsClass = p.getTree().getInfoFromCache(param.getContainedTypeName());
+				frame.dispatch(new RunAt<Frame>(this) {
 					@Override
-					public void run() {
-						panel = instanceAtFrame.preparePanel(param, framsClass);
+					protected void runAt() {
+						panel = treeAtFrame.preparePanel(param, framsClass);
 						fillPanelWithValues();
 					}
@@ -360,7 +318,4 @@
 		return tooltip;
 	}
-
-
-
 
 	/*public void subscribe(final EventParam eventParam) {
@@ -408,46 +363,43 @@
 			return;
 		}
-		userSubscriptions.get(eventParam).unsubscribe(new LoggingStateCallback<Connection>(log, "unsubscribed " + eventParam));
+		userSubscriptions.get(eventParam).unsubscribe(new LoggingStateCallback(log, "unsubscribed " + eventParam));
 		userSubscriptions.remove(eventParam);
 	}
 
-/*
-
-	@Override
-	public void onChildChange(final Child child, ListChange.Action action) {
-		assert browser.manager.isActive();
-
-		switch (action) {
-			case Remove: {
-				Dispatching.invokeDispatch(browser, browser.manager, new Runnable() {
-					@Override
-					public void run() {
-						assert browser.manager.isActive();
-						final TreeNode treeNode = (TreeNode) child.getUserObject();
-						if (treeNode == null) {
-							log.error("child " + child + " had no tree node attached");
-							return;
-						}
-						browser.invokeLater(new Runnable() {
-							@Override
-							public void run() {
-								assert browser.isActive();
-								TreePath path = browser.startChange();
-								//assert treeNode.getParent() == TreeNode.this;
-								if (treeNode.getParent() != null) {
-									browser.treeModel.removeNodeFromParent(treeNode);
-								}
-								//remove(treeNode);
-								browser.markNodeChanged(TreeNode.this, path);
-							}
-						});
-					}
-				});
-				break;
-			}
-		}
-
-	}
-*/
+	// @Override
+	// public void onChildChange(final Child child, ListChange.Action action) {
+	// assert browser.manager.isActive();
+
+	// switch (action) {
+	// case Remove: {
+	// Dispatching.invokeDispatch(browser, browser.manager, new Runnable() {
+	// @Override
+	// public void run() {
+	// assert browser.manager.isActive();
+	// final TreeNode treeNode = (TreeNode) child.getUserObject();
+	// if (treeNode == null) {
+	// log.error("child " + child + " had no tree node attached");
+	// return;
+	// }
+	// browser.invokeLater(new Runnable() {
+	// @Override
+	// public void run() {
+	// assert browser.isActive();
+	// TreePath path = browser.startChange();
+	// //assert treeNode.getParent() == TreeNode.this;
+	// if (treeNode.getParent() != null) {
+	// browser.treeModel.removeNodeFromParent(treeNode);
+	// }
+	// //remove(treeNode);
+	// browser.markNodeChanged(TreeNode.this, path);
+	// }
+	// });
+	// }
+	// });
+	// break;
+	// }
+	// }
+
+	// }
 
 	public String getName() {
@@ -486,5 +438,5 @@
 	}
 
-	public Path getInstancePath() {
+	public Path getTreePath() {
 		assert frame.isActive();
 		return path;
@@ -501,8 +453,8 @@
 		final Path p = path;
 
-		for (Map.Entry<ValueControl, Object> e : localChanges.entrySet()) {
-			storeValue(p, e.getKey().getParam(), e.getValue(), new AbstractStateFunctor() {
+		for (Map.Entry<ValueControl, Object> e : changes.entrySet()) {
+			set(p, e.getKey().getParam(), e.getValue(), new FutureHandler<Integer>(this) {
 				@Override
-				public void call() {
+				protected void result(Integer flag) {
 					counter.set(counter.get() - 1);
 					if (counter.get() != 0) {
@@ -510,13 +462,19 @@
 					}
 					log.debug("applied changes for: " + p);
-					frame.dispatch(new RunAt<Frame>() {
+					frame.dispatch(new RunAt<Frame>(this) {
 						@Override
-						public void run() {
+						protected void runAt() {
 							fillPanelWithValues();
 						}
 					});
 				}
+
 			});
 		}
 	}
+
+	@Override
+	public void handle(FramsticksException exception) {
+		frame.handle(exception);
+	}
 }
Index: java/main/src/main/java/com/framsticks/gui/console/Console.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/Console.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/console/Console.java	(revision 97)
@@ -0,0 +1,136 @@
+package com.framsticks.gui.console;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.communication.Connection;
+import com.framsticks.gui.FrameJoinable;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableParent;
+import com.framsticks.util.dispatching.JoinableState;
+import com.framsticks.util.dispatching.RunAt;
+
+@FramsClassAnnotation
+public abstract class Console extends FrameJoinable implements JoinableParent {
+	private static final Logger log = Logger.getLogger(Console.class);
+
+	/**
+	 * Painter coloring manager responses before display.
+	 */
+	protected ConsolePainter consolePainter;
+
+	protected Connection connection;
+
+	protected JPanel panel;
+
+	/**
+	 * @param connection
+	 */
+	public Console() {
+		setTitle("console");
+	}
+
+	/**
+	 * @return the connection
+	 */
+	public Connection getConnection() {
+		return connection;
+	}
+
+	@Override
+	public String getName() {
+		return connection != null ? "console for " + connection.getName() : "console";
+	}
+
+	@Override
+	protected void initializeGui() {
+		super.initializeGui();
+		panel = new JPanel();
+		panel.setLayout(new BorderLayout());
+		panel.setSize(new Dimension(440, 400));
+		panel.setMinimumSize(new Dimension(440, 400));
+
+		JTextPane text = new JTextPane();
+		consolePainter = new ConsolePainter(text);
+
+		text.setEditable(false);
+		final JScrollPane scrollText = new JScrollPane(text);
+		scrollText.setBorder(BorderFactory.createEtchedBorder());
+
+		JPanel scrollPanel = new JPanel();
+		scrollPanel.setLayout(new BorderLayout());
+		scrollPanel.add(scrollText, BorderLayout.CENTER);
+		scrollPanel.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7));
+
+		panel.add(scrollPanel, BorderLayout.CENTER);
+
+		getSwing().getContentPane().add(panel, BorderLayout.CENTER);
+
+		log.debug("initialized gui");
+	}
+
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		if (joinable == connection) {
+			proceedToState(state);
+		}
+	}
+
+	protected ExceptionResultHandler getExceptionHandler() {
+		return new ExceptionResultHandler() {
+
+			@Override
+			public void handle(FramsticksException exception) {
+				throw exception;
+
+			}
+		};
+	}
+
+	@Override
+	protected void joinableStart() {
+		if (connection == null) {
+			throw new FramsticksException().msg("connection was not set").arg("console", this);
+		}
+		super.joinableStart();
+		Dispatching.use(connection, this);
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		Dispatching.drop(connection, this);
+		super.joinableInterrupt();
+	}
+
+	@Override
+	protected void joinableFinish() {
+		super.joinableFinish();
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.join(connection);
+		super.joinableJoin();
+	}
+
+	protected void dispatchWrite(final String line) {
+		dispatch(new RunAt<Console>(getExceptionHandler()) {
+			@Override
+			protected void runAt() {
+				consolePainter.userLine(line);
+			}
+		});
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/console/ConsolePainter.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/ConsolePainter.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/console/ConsolePainter.java	(revision 97)
@@ -0,0 +1,211 @@
+package com.framsticks.gui.console;
+
+import com.framsticks.communication.File;
+import com.framsticks.util.FramsticksException;
+// import org.apache.log4j.Logger;
+
+// import java.awt.Color;
+
+import javax.swing.JTextPane;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.SimpleAttributeSet;
+
+/**
+ * Class paints messages.
+ */
+public class ConsolePainter {
+	// private static final Logger log = Logger.getLogger(ConsolePainter.class.getName());
+
+	private final Document doc;
+	private final JTextPane textPane;
+	// private Color c1 = new Color(192, 0, 0);
+	// private Color c2 = new Color(84, 141, 212);
+	// private Color c3 = new Color(118, 146, 60);
+	// private Color c4 = new Color(0, 0, 128);
+	// private final SimpleLinePainter linePainter1;
+	// private final SimpleLinePainter linePainter2;
+	private final SimpleAttributeSet set = new SimpleAttributeSet();
+
+
+	/**
+	 * Constructor sets reference to pane with text.
+	 * @param pane Pane where text is displaying.
+	 */
+	public ConsolePainter(JTextPane pane) {
+		this.textPane = pane;
+		doc = textPane.getStyledDocument();
+		// linePainter1 = new SimpleLinePainter(textPane, new Color(224, 224, 255));
+		// linePainter2 = new SimpleLinePainter(textPane, new Color(240, 240, 255));
+	}
+
+	/**
+	 * Paints message.
+	 */
+	public void paintMessage(File file) {
+
+
+		String line;
+		// Boolean boldNextId = false;
+		// Boolean doNotPaint = false;
+
+		while ((line = file.getContent().readLine()) != null) {
+			paintLine(line + "\n");
+			/*
+			if (doNotPaint) {
+				plainText(line);
+				if (line.endsWith("~\n")) {
+					doNotPaint = false;
+				}
+				continue;
+			}
+
+			int indColon = line.indexOf(':');
+
+			if (indColon == -1) {
+				String word = firstWord(line);
+				String rest = line.substring(word.length());
+				Color col = c1;
+
+				if (word.startsWith("ok")) {
+					col = Color.BLACK;
+				} else if (word.startsWith("error")) {
+					col = Color.RED;
+				}
+
+				paintLine(word, col, "b");
+				paintLine(rest, Color.BLACK, "b");
+				continue;
+			}
+
+			if (indColon == line.length() - 2) {
+				String before = line.substring(0, indColon);
+				String type = "b";
+
+				if (before.equals("class")) {
+					boldNextId = true;
+				}
+
+				paintLine(before + ":", c2, type);
+				paintLine("\n", Color.BLACK, "");
+				continue;
+			}
+			String before = line.substring(0, indColon);
+			String after = line.substring(indColon + 1);
+
+			String type;
+
+			if (before.equals("id") && boldNextId) {
+				type = "b";
+				boldNextId = false;
+			} else {
+				type = "";
+			}
+
+			paintLine(before + ":", c3, "b");
+			paintLine(after, Color.BLACK, type);
+
+			if (after.startsWith("~")) {
+				doNotPaint = true;
+			}*/
+
+		}
+
+		scrollDown();
+
+	}
+
+	private void paintLine(String text) {
+		//TODO colouring output, maybe using parsers?
+		try {
+			doc.insertString(doc.getLength(), text, set);
+		} catch (BadLocationException e) {
+			throw new FramsticksException().msg("failed document insertion").cause(e);
+		}
+	}
+	/**
+	 * Paints line of text.
+	 * @param text Line of text to be painted.
+	 * @param color Font color.
+	 * @param type Font attributes [b|i|u] (bold | italic | underline)
+	 */
+	/*
+	private void paintLine(String text, Color color, String type) {
+		SimpleAttributeSet set = new SimpleAttributeSet();
+
+		if (type.contains("b")) {
+			StyleConstants.setBold(set, true);
+		}
+
+		if (type.contains("i")) {
+			StyleConstants.setItalic(set, true);
+		}
+
+		if (type.contains("u")) {
+			StyleConstants.setUnderline(set, true);
+		}
+
+		StyleConstants.setFontFamily(set, "Monospaced");
+		StyleConstants.setForeground(set, color);
+		textPane.setCharacterAttributes(set, true);
+
+		try {
+			doc.insertString(doc.getLength(), text, set);
+		} catch (BadLocationException e) {
+			e.printStackTrace();
+		}
+
+	}
+	*/
+
+
+
+	/**
+	 * Returns first word in text line.
+	 * @param line Line of text.
+	 * @return First word in text line (with space char).
+	 */
+	// private String firstWord(String line) {
+	// 	String result;
+	// 	int spaceIndex = line.indexOf(' ');
+
+	// 	if (spaceIndex == -1) {
+	// 		result = line;
+	// 	} else {
+	// 		result = line.substring(0, spaceIndex + 1);
+	// 	}
+
+	// 	return result;
+	// }
+
+	/**
+	 * Paint line as plain text.
+	 * @param msg
+	 */
+	/*
+	private void plainText(String msg) {
+		paintLine(msg, Color.BLACK, "");
+	}
+	*/
+
+	/**
+	 * Adds message typed by user.
+	 * @param msg Message typed by user.
+	 */
+	public void userLine(String line) {
+		// paintLine("[USER]> "/*, c4, "b"*/);
+		scrollDown();
+		// linePainter1.resetHighlight();
+		paintLine(line);
+		paintLine("\n");
+		scrollDown();
+	}
+
+	/**
+	 * Scrolling text pane.
+	 */
+	private void scrollDown() {
+		// textPane.setCaretPosition(doc.getLength() - 1);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/console/DirectConsole.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/DirectConsole.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/console/DirectConsole.java	(revision 97)
@@ -0,0 +1,75 @@
+package com.framsticks.gui.console;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import com.framsticks.communication.ClientSideRawConnection;
+import com.framsticks.communication.ConnectionListener;
+import com.framsticks.params.annotations.AutoAppendAnnotation;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+
+@FramsClassAnnotation
+public class DirectConsole extends InteractiveConsole implements ConnectionListener {
+
+	/**
+	 * @param connection
+	 */
+	public DirectConsole() {
+	}
+
+	@AutoAppendAnnotation
+	public DirectConsole setConnection(ClientSideRawConnection connection) {
+		this.connection = connection;
+		return this;
+	}
+
+	/**
+	 * @return the connection
+	 */
+	@Override
+	public ClientSideRawConnection getConnection() {
+		return (ClientSideRawConnection) connection;
+	}
+
+
+	protected void sendImplementation(String line) {
+		getConnection().send(line, ThrowExceptionHandler.getInstance());
+	}
+
+	/**
+	 * Creates commands tip list.
+	 * @param startText Text that user typed.
+	 */
+	protected void findCompletionPropositions(String prefix) {
+		List<String> propositions = new LinkedList<String>();
+		for (String entry : history) {
+			if (entry.startsWith(prefix)) {
+				propositions.add(entry);
+			}
+		}
+		processCompletionResult(prefix, propositions);
+	}
+
+	@Override
+	protected void joinableStart() {
+		super.joinableStart();
+		connection.getListeners().add(this);
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		connection.getListeners().remove(this);
+		super.joinableInterrupt();
+	}
+
+	@Override
+	public void connectionOutgoing(String line) {
+		dispatchWrite(line);
+	}
+
+	@Override
+	public void connectionIncomming(String line) {
+		dispatchWrite(line);
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/console/InteractiveConsole.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/InteractiveConsole.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/console/InteractiveConsole.java	(revision 97)
@@ -0,0 +1,242 @@
+package com.framsticks.gui.console;
+
+import java.awt.AWTKeyStroke;
+import java.awt.BorderLayout;
+import java.awt.KeyboardFocusManager;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.font.FontRenderContext;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JTextField;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.lang.Strings;
+
+@FramsClassAnnotation
+public abstract class InteractiveConsole extends Console {
+
+	/**
+	 * Text field for typing commands.
+	 */
+	protected JTextField commandLine;
+	protected JButton sendButton;
+
+	protected final LinkedList<String> history = new LinkedList<>();
+	protected ListIterator<String> historyCursor;
+
+	public void setCommandLine(String command) {
+		commandLine.setText(command);
+	}
+
+	/**
+	 * @param connection
+	 */
+	public InteractiveConsole() {
+	}
+
+	@Override
+	protected void initializeGui() {
+		// TODO Auto-generated method stub
+		super.initializeGui();
+
+		commandLine = new JTextField();
+
+		commandLine.addKeyListener(new KeyListener() {
+			@Override
+			public void keyTyped(KeyEvent e) {
+
+			}
+
+			@Override
+			public void keyPressed(KeyEvent e) {
+				onKeyPressed(e.getKeyCode());
+			}
+
+			@Override
+			public void keyReleased(KeyEvent e) {
+			}
+		});
+
+		commandLine.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.<AWTKeyStroke> emptySet());
+
+		completionPopup = new JPopupMenu();
+
+		// completionPopupAction = new AbstractAction() {
+		//	@Override
+		//	public void actionPerformed(ActionEvent event) {
+		//		JMenuItem item = (JMenuItem) event.getSource();
+		//		commandLine.setText(item.getText());
+		//	}
+		// };
+
+		sendButton = new JButton("Send");
+		sendButton.setName("send");
+		sendButton.addActionListener(new ActionListener() {
+
+			public void actionPerformed(final ActionEvent e) {
+				sendCurrent();
+			}
+		});
+
+		final Box cmdBox = new Box(BoxLayout.LINE_AXIS);
+		cmdBox.add(commandLine);
+		cmdBox.add(Box.createHorizontalStrut(10));
+		cmdBox.add(sendButton);
+		cmdBox.setBorder(BorderFactory.createEmptyBorder(0, 7, 7, 7));
+
+		panel.add(cmdBox, BorderLayout.PAGE_END);
+
+		getSwing().addWindowListener(new WindowAdapter() {
+			public void windowOpened(WindowEvent e) {
+				commandLine.requestFocus();
+			}
+		});
+
+
+	}
+
+
+	protected abstract void findCompletionPropositions(String prefix);
+
+	@SuppressWarnings("serial")
+	protected void processCompletionResult(String prefix, List<String> propositions) {
+		assert isActive();
+		if (propositions.isEmpty()) {
+			return;
+		}
+		if (!commandLine.getText().equals(prefix)) {
+			return;
+		}
+		if (propositions.size() == 1) {
+			commandLine.setText(propositions.get(0));
+			return;
+		}
+
+		Iterator<String> i = propositions.iterator();
+		String common = i.next();
+		while (i.hasNext()) {
+			common = Strings.commonPrefix(common, i.next());
+		}
+		if (!prefix.equals(common)) {
+			commandLine.setText(common);
+			return;
+		}
+
+		completionPopup.setVisible(false);
+		completionPopup.removeAll();
+
+		for (final String c : propositions) {
+			completionPopup.add(new JMenuItem(new AbstractAction(c) {
+				@Override
+				public void actionPerformed(ActionEvent e) {
+					commandLine.setText(c);
+				}
+			}));
+		}
+
+
+		double width = commandLine.getFont().getStringBounds(prefix, new FontRenderContext(null, false, false)).getWidth();
+		completionPopup.show(commandLine, (int) width, 0);
+		completionPopup.requestFocus();
+	}
+
+	protected JPopupMenu completionPopup;
+
+
+	private void onKeyPressed(int keyCode) {
+		if (keyCode == KeyEvent.VK_TAB) {
+			try {
+				findCompletionPropositions(commandLine.getText());
+			} catch (FramsticksException e) {
+				handle(e);
+			}
+			return;
+		}
+
+		if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN) {
+			boolean up = (keyCode == KeyEvent.VK_UP);
+			if (history.isEmpty()) {
+				return;
+			}
+
+			String line;
+			if (up) {
+				if (historyCursor == null) {
+					historyCursor = history.listIterator(0);
+				}
+				if (historyCursor.hasNext()) {
+					line = historyCursor.next();
+				} else {
+					historyCursor = null;
+					line = "";
+				}
+			} else {
+				if (historyCursor == null) {
+					historyCursor = history.listIterator(history.size());
+				}
+				if (historyCursor.hasPrevious()) {
+					line = historyCursor.previous();
+				} else {
+					historyCursor = null;
+					line = "";
+				}
+			}
+			commandLine.setText(line);
+			return;
+		}
+
+		if (keyCode == KeyEvent.VK_ENTER) {
+			sendCurrent();
+			return;
+		}
+
+	}
+
+	protected abstract void sendImplementation(String line);
+
+	/**
+	 * Sends message to manager and adds message to console frame.
+	 *
+	 * Message is not put into the text area by that method, because
+	 * in DirectConsole it is done by means of listening on Connection.
+	 */
+	public void sendCurrent() {
+		assert isActive();
+		String line = commandLine.getText();
+		history.remove(line);
+		history.add(0, line);
+		historyCursor = null;
+		commandLine.setText("");
+
+		sendImplementation(line);
+
+	}
+
+	/**
+	 * Adds query to console window.
+	 *
+	 * @param line Line of string query.
+	 */
+	protected void paintLine(String line) {
+		consolePainter.userLine(line);
+	}
+
+
+}
Index: java/main/src/main/java/com/framsticks/gui/console/ManagedConsole.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/ManagedConsole.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/console/ManagedConsole.java	(revision 97)
@@ -0,0 +1,121 @@
+package com.framsticks.gui.console;
+
+import java.util.LinkedList;
+import java.util.List;
+
+
+import com.framsticks.communication.ClientSideManagedConnection;
+import com.framsticks.communication.ClientSideResponseFuture;
+import com.framsticks.communication.File;
+import com.framsticks.communication.Request;
+import com.framsticks.communication.Response;
+import com.framsticks.communication.queries.ApplicationRequest;
+import com.framsticks.core.Path;
+import static com.framsticks.core.TreeOperations.*;
+import com.framsticks.gui.SwingDispatcher;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.annotations.AutoAppendAnnotation;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.remote.RemoteTree;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Containers;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
+
+@FramsClassAnnotation
+public class ManagedConsole extends InteractiveConsole {
+
+	protected RemoteTree tree;
+
+	/**
+	 * @param connection
+	 */
+	public ManagedConsole() {
+	}
+
+	/**
+	 * @return the connection
+	 */
+	@Override
+	public ClientSideManagedConnection getConnection() {
+		return (ClientSideManagedConnection) connection;
+	}
+
+	protected void sendImplementation(String line) {
+		if (!connection.isConnected()) {
+			throw new FramsticksException().msg("not connected").arg("console", this);
+		}
+		//Move that to managed connection
+		ApplicationRequest request;
+		try {
+			Pair<String, String> command = Strings.splitIntoPair(line, ' ', "");
+			request = Casting.throwCast(ApplicationRequest.class, Request.createRequestByTypeString(command.first));
+			request.parseRest(command.second);
+		} catch (FramsticksException e) {
+			throw new FramsticksException().msg("invalid line").arg("line", line).cause(e);
+		}
+
+		paintLine(line);
+
+		getConnection().send(request, SwingDispatcher.getInstance(), new ClientSideResponseFuture(this) {
+			@Override
+			protected void processOk(Response response) {
+				for (File f : response.getFiles()) {
+					consolePainter.paintMessage(f);
+				}
+			}
+		});
+	}
+
+	@Override
+	protected void findCompletionPropositions(final String prefix) {
+		Pair<CharSequence, CharSequence> command = Request.takeIdentifier(prefix);
+
+		Casting.throwCast(ApplicationRequest.class, Request.createRequestByTypeString(command.first.toString()));
+		// Pair<String, String> rest = Strings
+		Pair<CharSequence, CharSequence> rest = Request.takeIdentifier(command.second);
+		if (rest == null) {
+			List<String> propositions = new LinkedList<String>();
+			propositions.add(command.first.toString() + " /");
+			processCompletionResult(prefix, propositions);
+			return;
+		}
+
+		final String textual = rest.first.toString();
+		if (!textual.startsWith("/")) {
+			throw new FramsticksException().msg("invalid line").arg("line", prefix);
+		}
+		// final Iterator<String> iterator = Path.splitPath(textual);
+
+		resolve(tree, textual, new FutureHandler<Path>(this) {
+
+			@Override
+			protected void result(Path path) {
+				if (!textual.startsWith(path.getTextual())) {
+					throw new FramsticksException().msg("invalid state").arg("line", prefix).arg("path", path);
+				}
+
+				List<String> propositions = new LinkedList<String>();
+				String remaining = textual.substring(path.getTextual().length());
+				remaining = Path.PathBuilder.splitPath(remaining).next();
+
+				for (CompositeParam p : Containers.filterInstanceof(bindAccess(path).getParams(), CompositeParam.class)) {
+					if (p.getId().startsWith(remaining)) {
+						propositions.add(p.getId());
+					}
+				}
+				processCompletionResult(prefix, propositions);
+			}
+		});
+
+
+	}
+
+	@AutoAppendAnnotation
+	public void setTree(RemoteTree tree) {
+		this.tree = tree;
+		connection = tree.getConnection();
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/console/SimpleLinePainter.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/SimpleLinePainter.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/console/SimpleLinePainter.java	(revision 97)
@@ -0,0 +1,70 @@
+package com.framsticks.gui.console;
+
+import javax.swing.text.*;
+import java.awt.*;
+
+/**
+ * Painter class to coloring text background.
+ */
+public class SimpleLinePainter extends
+		DefaultHighlighter.DefaultHighlightPainter {
+
+	private JTextComponent component;
+	private DefaultHighlighter highlighter;
+
+	/**
+	 * Constructor sets component reference.
+	 *
+	 * @param component Reference to painted component.
+	 * @param color     Background color.
+	 */
+	public SimpleLinePainter(JTextComponent component, Color color) {
+		super(color);
+
+		this.component = component;
+
+		highlighter = (DefaultHighlighter) component.getHighlighter();
+		highlighter.setDrawsLayeredHighlights(true);
+	}
+
+	/**
+	 * Adds highlight in line sets by offset.
+	 *
+	 * @param offset Line offset.
+	 */
+	public void addHighlight(int offset) {
+		try {
+			highlighter.addHighlight(offset, offset + 1, this);
+		} catch (BadLocationException ignored) {
+		}
+	}
+
+	/**
+	 * Resets highlight.
+	 */
+	public void resetHighlight() {
+
+		Element root = component.getDocument().getDefaultRootElement();
+		int line = root.getElementIndex(component.getCaretPosition());
+		Element lineElement = root.getElement(line);
+		int start = lineElement.getStartOffset();
+		addHighlight(start);
+	}
+
+
+	public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds,
+							JTextComponent c, View view) {
+		try {
+			Rectangle r = c.modelToView(offs0);
+			r.x = 0;
+			r.width = c.getSize().width;
+
+			g.setColor(getColor());
+			g.fillRect(r.x, r.y, r.width, r.height);
+			return r;
+		} catch (BadLocationException e) {
+			return null;
+		}
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/console/TrackConsole.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/TrackConsole.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/gui/console/TrackConsole.java	(revision 97)
@@ -0,0 +1,43 @@
+package com.framsticks.gui.console;
+
+import com.framsticks.communication.Connection;
+import com.framsticks.communication.ConnectionListener;
+import com.framsticks.params.annotations.AutoAppendAnnotation;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+
+@FramsClassAnnotation
+public class TrackConsole extends Console implements ConnectionListener {
+
+	public TrackConsole() {
+	}
+
+	@AutoAppendAnnotation
+	public TrackConsole setConnection(Connection connection) {
+		this.connection = connection;
+		return this;
+	}
+
+	@Override
+	protected void joinableStart() {
+		super.joinableStart();
+		connection.getListeners().add(this);
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		connection.getListeners().remove(this);
+		super.joinableInterrupt();
+	}
+
+
+	@Override
+	public void connectionOutgoing(String line) {
+		dispatchWrite(line);
+	}
+
+	@Override
+	public void connectionIncomming(String line) {
+		dispatchWrite(line);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/Control.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/Control.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/controls/Control.java	(revision 97)
@@ -6,7 +6,8 @@
 import javax.swing.JPanel;
 
-import com.framsticks.gui.Frame;
 import com.framsticks.params.Flags;
 import com.framsticks.params.Param;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 
 /**
@@ -14,5 +15,5 @@
  */
 @SuppressWarnings("serial")
-public abstract class Control extends JPanel {
+public abstract class Control extends JPanel implements ExceptionResultHandler {
 
 	public static final int LINE_HEIGHT = 36;
@@ -20,5 +21,4 @@
 	// private static final Logger log = Logger.getLogger(Control.class.getName());
 
-	protected Frame frame;
 	protected final Param param;
 	protected ControlOwner owner;
@@ -36,8 +36,4 @@
 	}
 
-	public void setFrame(Frame frame) {
-		this.frame = frame;
-	}
-
 	public void setOwner(ControlOwner owner) {
 		this.owner = owner;
@@ -53,3 +49,8 @@
 		return param.toString();
 	}
+
+	@Override
+	public void handle(FramsticksException exception) {
+		owner.handle(exception);
+	}
 }
Index: java/main/src/main/java/com/framsticks/gui/controls/ControlOwner.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ControlOwner.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/controls/ControlOwner.java	(revision 97)
@@ -4,6 +4,7 @@
 
 import com.framsticks.gui.TreeNode;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 
-public interface ControlOwner {
+public interface ControlOwner extends ExceptionResultHandler {
 
 	public JPanel getPanel();
Index: java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 97)
@@ -1,5 +1,5 @@
 package com.framsticks.gui.controls;
 
-import com.framsticks.core.Instance;
+import com.framsticks.core.Tree;
 import com.framsticks.core.Path;
 import com.framsticks.gui.Gui;
@@ -8,8 +8,8 @@
 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.dispatching.Future;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.FutureHandler;
 import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
 
 import javax.swing.*;
@@ -58,20 +58,19 @@
 
 				log.debug("calling " + getParam() + " on " + treeNode);
-				final Path path = treeNode.getInstancePath();
+				final Path path = treeNode.getTreePath();
 
 				final List<Object> arguments = new LinkedList<Object>();
 				for (Param arg : getParam().getArgumentsType()) {
-					arguments.add(((ValueControl) components.get(arg)).getCurrentValue());
+					Object value = components.get(arg).getCurrentValue();
+					arguments.add(value);
+					log.debug("argument " + arg + ": " + value);
 				}
+				//TODO FEH: make it show dialog
+				final ExceptionResultHandler handler = ThrowExceptionHandler.getInstance();
 
-				path.getInstance().dispatch(new RunAt<Instance>() {
+				path.getTree().dispatch(new RunAt<Tree>(handler) {
 					@Override
-					public void run() {
-						path.getInstance().call(path, getParam(), arguments.toArray(), new Future<Object>() {
-
-							@Override
-							public void handle(FramsticksException e) {
-								Logging.log(log, "call procedure", path, e);
-							}
+					protected void runAt() {
+						path.getTree().call(path, getParam(), arguments.toArray(), new FutureHandler<Object>(handler) {
 
 							@Override
Index: java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 97)
@@ -104,5 +104,5 @@
 
 		JPanel sliderPanel = new JPanel();
-		sliderPanel.setLayout(new BoxLayout(sliderPanel, BoxLayout.LINE_AXIS));
+		// sliderPanel.setLayout(new BoxLayout(sliderPanel, BoxLayout.LINE_AXIS));
 
 
Index: java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java	(revision 97)
@@ -9,12 +9,11 @@
 public class TextAreaControl extends TextControl {
 
-	// private static final Logger log = Logger.getLogger(TextAreaControl.class.getName());
-
-	protected JTextArea textArea;
-	protected JScrollPane textScrollPane;
+	protected final JTextArea textArea;
+	protected final JScrollPane textScrollPane;
 
 	public TextAreaControl(PrimitiveParam<?> valueParam) {
 		super(valueParam);
 		textArea = new JTextArea();
+		textArea.setName("value");
 		textArea.setLineWrap(true);
 		textArea.setWrapStyleWord(true);
Index: java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java	(revision 97)
@@ -7,4 +7,5 @@
 import com.framsticks.params.PrimitiveParam;
 import com.framsticks.params.ReassignResult;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.swing.TooltipConstructor;
 
@@ -73,5 +74,6 @@
 			return res.getValue();
 		} catch (CastFailure e) {
-			log.error("cast failure when setting param " + param + " to value " + candidate + ": " + e);
+			//TODO just throw here, but check where that function is being used
+			handle(new FramsticksException().msg("invalid value in control").arg("param", param).arg("value", candidate).cause(e));
 		}
 		return oldValue;
Index: java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java	(revision 97)
@@ -0,0 +1,151 @@
+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.Mode;
+import com.framsticks.core.Tree;
+import com.framsticks.core.Path;
+import com.framsticks.params.*;
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.parsers.Savers;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.AbstractJoinable;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableParent;
+import com.framsticks.util.dispatching.JoinableState;
+import static com.framsticks.core.TreeOperations.*;
+
+import java.net.Socket;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class ClientAtServer extends AbstractJoinable implements RequestHandler, JoinableParent {
+
+	protected final Server server;
+	protected final Tree tree;
+	protected final ServerSideManagedConnection connection;
+
+	public ClientAtServer(Server server, Socket socket) {
+		this.server = server;
+		this.tree = server.hosted;
+		this.connection = new ServerSideManagedConnection(socket, this);
+	}
+
+	@Override
+	public String getName() {
+		return connection + " to " + server;
+	}
+
+	@Override
+	public void handle(final ApplicationRequest request, final ServerSideResponseFuture responseCallback) {
+		assureNotEmpty(request.getPath());
+
+		resolve(tree, request.getPath(), new FutureHandler<Path>(responseCallback) {
+			@Override
+			protected void result(final Path path) {
+
+				// final AccessInterface access = tree.prepareAccess(path);
+				final AccessInterface access = bindAccess(path);
+
+				if (request instanceof SetRequest) {
+					SetRequest setRequest = (SetRequest) request;
+					//TODO Primitive Param?
+					tree.set(path, access.getFramsClass().getParamEntry(setRequest.getField(), PrimitiveParam.class), setRequest.getValue(), new FutureHandler<Integer>(responseCallback) {
+						@Override
+						protected void result(Integer flag) {
+							responseCallback.pass(new Response(true, Flags.write(flag, null), null));
+
+						}
+					});
+					return;
+				}
+
+				if (request instanceof GetRequest) {
+					tree.get(path, Mode.FETCH, new FutureHandler<Object>(responseCallback) {
+
+						@Override
+						protected void result(Object result) {
+							if (result != access.getSelected()) {
+								throw new FramsticksException().msg("mismatch objects during fetch").arg("path", path);
+							}
+							// TODO Auto-generated method stub
+							List<File> files = new LinkedList<File>();
+							ListSink sink = new ListSink();
+							access.save(sink);
+							files.add(new File(path.getTextual(), new ListSource(sink.getOut())));
+							responseCallback.pass(new Response(true, "", files));
+						}
+					});
+
+					return;
+				}
+				if (request instanceof CallRequest) {
+					final CallRequest callRequest = (CallRequest) request;
+					tree.call(path, access.getFramsClass().getParamEntry(callRequest.getProcedure(), ProcedureParam.class), callRequest.getArguments().toArray(), new FutureHandler<Object>(responseCallback) {
+						@Override
+						protected void result(Object result) {
+							ListSink sink = new ListSink();
+							sink.print("Result:").breakLine();
+							sink.print("value:").print("[");
+							if (result != null) {
+								sink.print(result);
+							}
+							sink.print("]");
+
+							responseCallback.pass(new Response(true, "", File.single(new File("", new ListSource(sink.getOut())))));
+						}
+					});
+					return;
+				}
+				if (request instanceof InfoRequest) {
+					FramsClass framsClass = getInfo(path);
+					if (framsClass == null) {
+						throw new FramsticksException().msg("info should be available");
+					}
+					responseCallback.pass(new Response(true, null, File.single(new File(path.getTextual(), new ListSource(Savers.saveFramsClass(new ListSink(), framsClass).getOut())))));
+					return;
+				}
+
+				throw new FramsticksException().msg("invalid request type: " + request.getCommand());
+			}
+		});
+
+	}
+
+	@Override
+	protected void joinableStart() {
+		Dispatching.use(connection, this);
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		Dispatching.drop(connection, this);
+	}
+
+	@Override
+	protected void joinableFinish() {
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.join(connection);
+	}
+
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		proceedToState(state);
+	}
+
+
+}
Index: java/main/src/main/java/com/framsticks/hosting/InstanceClient.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/InstanceClient.java	(revision 96)
+++ 	(revision )
@@ -1,156 +1,0 @@
-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.util.FramsticksException;
-import com.framsticks.util.dispatching.AbstractJoinable;
-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 static com.framsticks.core.InstanceUtils.*;
-
-import java.net.Socket;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author Piotr Sniegowski
- */
-public class InstanceClient extends AbstractJoinable implements RequestHandler, JoinableParent {
-
-	protected final Server server;
-	protected final Instance instance;
-	protected final ServerConnection connection;
-
-	public InstanceClient(Server server, Socket socket) {
-		this.server = server;
-		this.instance = server.hosted;
-		this.connection = new ServerConnection(socket, this);
-	}
-
-	@Override
-	public String getName() {
-		return connection + " to " + server;
-	}
-
-	@Override
-	public void handle(final ApplicationRequest request, final ResponseCallback<?> responseCallback) {
-		assureNotEmpty(request.getPath());
-
-		resolve(instance, request.getPath(), new Future<Path>(responseCallback) {
-			@Override
-			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) {
-					InstanceUtils.findInfo(path, new Future<FramsClass>(responseCallback) {
-						@Override
-						protected void result(FramsClass result) {
-							if (result == null) {
-								throw new FramsticksException().msg("failed to find info for access bind");
-							}
-							List<File> files = new LinkedList<File>();
-							AccessInterface access = bindAccess(path);
-
-							if (access == null) {
-								throw new FramsticksException().msg("failed to bind access");
-							}
-
-							ListSink sink = new ListSink();
-							access.save(sink);
-							files.add(new File(path.getTextual(), new ListSource(sink.getOut())));
-							responseCallback.process(new Response(true, "", files));
-						}
-					});
-					return;
-				}
-				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
-						protected void result(Object result) {
-							ListSink sink = new ListSink();
-							sink.print("Result:").breakLine();
-							sink.print("value:").print("[");
-							if (result != null) {
-								sink.print(result);
-							}
-							sink.print("]");
-
-							responseCallback.process(new Response(true, "", File.single(new File("", new ListSource(sink.getOut())))));
-						}
-					});
-					return;
-				}
-				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());
-			}
-		});
-
-	}
-
-	@Override
-	protected void joinableStart() {
-		Dispatching.use(connection, this);
-	}
-
-	@Override
-	protected void joinableInterrupt() {
-		Dispatching.drop(connection, this);
-	}
-
-	@Override
-	protected void joinableFinish() {
-	}
-
-	@Override
-	protected void joinableJoin() throws InterruptedException {
-		Dispatching.join(connection);
-	}
-
-	@Override
-	public void childChangedState(Joinable joinable, JoinableState state) {
-		proceedToState(state);
-	}
-
-
-}
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 97)
@@ -4,5 +4,5 @@
 import org.apache.log4j.Logger;
 
-import com.framsticks.core.Instance;
+import com.framsticks.core.Tree;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -17,4 +17,5 @@
 import com.framsticks.util.dispatching.RunAt;
 import com.framsticks.util.dispatching.Task;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
 
 import java.io.IOException;
@@ -32,6 +33,6 @@
 
 	protected ServerSocket acceptSocket;
-	protected Instance hosted;
-	protected final JoinableCollection<InstanceClient> clients = new JoinableCollection<InstanceClient>();
+	protected Tree hosted;
+	protected final JoinableCollection<ClientAtServer> clients = new JoinableCollection<ClientAtServer>();
 
 	public static class Accept {
@@ -80,12 +81,12 @@
 	 * @return the hosted
 	 */
-	public Instance getHosted() {
+	public Tree getHosted() {
 		return hosted;
 	}
 
 	@AutoAppendAnnotation
-	public void setHosted(Instance hosted) {
+	public void setHosted(Tree hosted) {
 		if (this.hosted != null) {
-			throw new FramsticksException().msg("hosted instance is already set").arg("current", this.hosted);
+			throw new FramsticksException().msg("hosted tree is already set").arg("current", this.hosted);
 		}
 		this.hosted = hosted;
@@ -123,7 +124,8 @@
 			return;
 		}
-		acceptThread.dispatch(new RunAt<Accept>() {
+		//TODO TEH
+		acceptThread.dispatch(new RunAt<Accept>(ThrowExceptionHandler.getInstance()) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				try {
 					log.debug("accepting");
@@ -131,8 +133,8 @@
 					assert socket != null;
 					log.debug("accepted socket: " + socket.getInetAddress().getHostAddress());
-					hosted.dispatch(new RunAt<Instance>() {
+					hosted.dispatch(new RunAt<Tree>(this) {
 						@Override
-						public void run() {
-							InstanceClient client = new InstanceClient(Server.this, socket);
+						protected void runAt() {
+							ClientAtServer client = new ClientAtServer(Server.this, socket);
 							clients.add(client);
 							log.info("client connected: " + client);
@@ -148,7 +150,7 @@
 
 	protected void tryBind(int when) {
-		acceptThread.dispatch(new Task<Accept>(when) {
+		acceptThread.dispatch(new Task<Accept>(ThrowExceptionHandler.getInstance(), when) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				try {
 					acceptSocket.bind(new InetSocketAddress(port));
Index: java/main/src/main/java/com/framsticks/model/f0/Schema.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/f0/Schema.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/model/f0/Schema.java	(revision 97)
@@ -35,5 +35,5 @@
 	}
 
-	protected static Schema defaultSchema;
+	private static Schema defaultSchema;
 
 	public synchronized static Schema getDefaultSchema() {
Index: java/main/src/main/java/com/framsticks/params/AccessInterface.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/AccessInterface.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/params/AccessInterface.java	(revision 97)
@@ -56,5 +56,5 @@
 	void save(SinkInterface sink);
 
-	void load(SourceInterface stream) throws Exception;
+	void load(SourceInterface stream);
 
 	/**
Index: java/main/src/main/java/com/framsticks/params/ListAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 97)
@@ -63,5 +63,5 @@
 
 	@Override
-	public void load(SourceInterface stream) throws Exception {
+	public void load(SourceInterface stream) {
 	}
 
Index: java/main/src/main/java/com/framsticks/params/ParamBuilder.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ParamBuilder.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/params/ParamBuilder.java	(revision 97)
@@ -504,5 +504,5 @@
 	}
 
-	private static Pattern addressPattern = Pattern.compile("^([^\\(]+)?\\(([^\\)]*)\\)$");
+	private static Pattern signaturePattern = Pattern.compile("^([^\\(]+)?\\(([^\\)]*)\\)$");
 
 	public ParamBuilder signature(String signature) {
@@ -513,5 +513,5 @@
 			return this;
 		}
-		Matcher matcher = addressPattern.matcher(signature);
+		Matcher matcher = signaturePattern.matcher(signature);
 		if (!matcher.matches()) {
 			throw new FramsticksException().msg("invalid signature");
Index: java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 97)
@@ -1,5 +1,4 @@
 package com.framsticks.params;
 
-import java.io.IOException;
 import java.util.Collection;
 
@@ -149,7 +148,4 @@
 	public void setMin(int i) {
 		PrimitiveParam<?> entry = framsClass.getParamEntry(i, PrimitiveParam.class);
-		if (entry == null) {
-			return;
-		}
 		Object min = entry.getMin(entry.getStorageType());
 		if (min != null) {
@@ -168,7 +164,4 @@
 	public void setMax(int i) {
 		PrimitiveParam<?> entry = framsClass.getParamEntry(i, PrimitiveParam.class);
-		if (entry == null) {
-			return;
-		}
 		Object max = entry.getMax(entry.getStorageType());
 		if (max != null) {
@@ -205,6 +198,5 @@
 	}
 
-	private Entry readEntry(SourceInterface source)
-			throws IOException {
+	private Entry readEntry(SourceInterface source) {
 
 		String line;
@@ -252,5 +244,5 @@
 
 	@Override
-	public void load(SourceInterface source) throws Exception {
+	public void load(SourceInterface source) {
 		//TODO not clearing values, because get from manager gives only fields, not children
 		//this.clearValues();
Index: java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java	(revision 97)
@@ -26,4 +26,5 @@
 		resultType = builder.getResultType();
 		argumentsType = builder.getArgumentsType();
+		assert argumentsType != null;
 
 		StringBuilder b = new StringBuilder().append("p");
@@ -49,5 +50,4 @@
 
 		signatureString = b.toString();
-		assert argumentsType != null;
 	}
 
Index: java/main/src/main/java/com/framsticks/parsers/F0Parser.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/F0Parser.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/parsers/F0Parser.java	(revision 97)
@@ -19,4 +19,5 @@
 import com.framsticks.params.PrimitiveParam;
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.io.Encoding;
 import com.framsticks.util.lang.Containers;
 import com.framsticks.util.lang.Pair;
@@ -85,5 +86,5 @@
 	public List<AccessInterface> parse() {
 
-		try (InputStreamReader reader = new InputStreamReader(is, "UTF-8")) {
+		try (InputStreamReader reader = new InputStreamReader(is, Encoding.getDefaultCharset())) {
 			BufferedReader br = new BufferedReader(reader);
 			while (br.ready()) {
Index: java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java	(revision 97)
@@ -4,6 +4,4 @@
 import org.apache.log4j.Logger;
 
-import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.util.*;
 
@@ -110,5 +108,5 @@
 	 * Starts reading the file.
 	 */
-	public Status go() throws Exception {
+	public Status go() {
 		log.trace("go");
 
@@ -159,5 +157,13 @@
 				continue;
 			}
-			log.warn("unknown line: " + currentLine);
+
+			// log.warn("unknown line: " + currentLine);
+			changeStatus(Status.OnError);
+			if (action == LoopAction.Break) {
+				break;
+			}
+			if (action == LoopAction.Continue) {
+				continue;
+			}
 		}
 
@@ -170,5 +176,5 @@
 	 * @throws Exception
 	 */
-	private LoopAction tryReadObject() throws Exception {
+	private LoopAction tryReadObject() {
 		if (status == Status.BeforeObject
 				|| (status == Status.BeforeUnknown && lastAccessInterface != null)) {
@@ -201,5 +207,5 @@
 	 * Checks whether some additional file shouldn't be included.
 	 */
-	private LoopAction isIncludeLine(String line) throws FileNotFoundException {
+	private LoopAction isIncludeLine(String line) {
 		try {
 			// found comment
@@ -374,5 +380,5 @@
 	 * Returns from included file.
 	 */
-	private boolean returnFromIncluded() throws IOException {
+	private boolean returnFromIncluded() {
 		if (fileStack.size() == 0) {
 			return false;
Index: java/main/src/main/java/com/framsticks/parsers/XmlLoader.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/XmlLoader.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/parsers/XmlLoader.java	(revision 97)
@@ -64,7 +64,4 @@
 		AccessInterface access = registry.createAccess(name);
 
-		if (access == null) {
-			throw new FramsticksException().msg("failed to find access interface").arg("name", name);
-		}
 		Object object = access.createAccessee();
 		assert object != null;
Index: java/main/src/main/java/com/framsticks/portals/Portal.java
===================================================================
--- java/main/src/main/java/com/framsticks/portals/Portal.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/portals/Portal.java	(revision 97)
@@ -2,7 +2,7 @@
 
 
-import com.framsticks.core.AbstractInstanceListener;
-import com.framsticks.core.Instance;
-import com.framsticks.core.InstanceUtils;
+import com.framsticks.core.AbstractTreeListener;
+import com.framsticks.core.Tree;
+import com.framsticks.core.TreeOperations;
 import com.framsticks.core.Path;
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -10,7 +10,8 @@
 import com.framsticks.util.Logging;
 import com.framsticks.util.dispatching.Dispatching;
-import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
 import com.framsticks.util.dispatching.JoinableCollection;
 import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
 
 import org.apache.log4j.Logger;
@@ -21,5 +22,5 @@
  */
 @FramsClassAnnotation
-public class Portal extends JoinableCollection<Instance> {
+public class Portal extends JoinableCollection<Tree> {
 
 	private final static Logger log = Logger.getLogger(Portal.class.getName());
@@ -33,20 +34,20 @@
 	// @Override
 	// public void run() {
-	// 	super.run();
-	// 	new PeriodicTask<Portal>(this, 1000) {
+	//	super.run();
+	//	new PeriodicTask<Portal>(this, 1000) {
 
-	// 		@Override
-	// 		public void run() {
-	// 			++counter;
-	// 			log.debug("counter is now: " + counter);
-	// 			again();
-	// 		}
-	// 	};
+	//		@Override
+	//		public void run() {
+	//			++counter;
+	//			log.debug("counter is now: " + counter);
+	//			again();
+	//		}
+	//	};
 	// }
 
 	@Override
-	public void add(final Instance instance) {
-		super.add(instance);
-		instance.addListener(new AbstractInstanceListener() {
+	public void add(final Tree tree) {
+		super.add(tree);
+		tree.addListener(new AbstractTreeListener() {
 			@Override
 			public void onRun(Exception e) {
@@ -59,8 +60,8 @@
 				}
 				final String path = "/simulator/genepools/groups/0/genotypes";
-				instance.dispatch(new RunAt<Instance>() {
+				tree.dispatch(new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
 					@Override
-					public void run() {
-						InstanceUtils.resolve(instance, path, new Future<Path>(Logging.logger(log, "resolve", path)) {
+					protected void runAt() {
+						TreeOperations.resolve(tree, path, new FutureHandler<Path>(Logging.logger(log, "resolve", path)) {
 							@Override
 							public void result(Path result) {
Index: java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java	(revision 97)
@@ -1,5 +1,7 @@
 package com.framsticks.remote;
 
-import static com.framsticks.core.InstanceUtils.*;
+import static com.framsticks.core.TreeOperations.*;
+
+import com.framsticks.core.Mode;
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
@@ -7,9 +9,10 @@
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.FramsClass;
-import com.framsticks.core.Instance;
+import com.framsticks.core.Tree;
 import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
 import com.framsticks.util.FramsticksException;
 import com.framsticks.util.Logging;
-import com.framsticks.util.StateFunctor;
 import com.framsticks.util.Stopwatch;
 import org.apache.log4j.Logger;
@@ -24,12 +27,12 @@
 	private final static Logger log = Logger.getLogger(RecursiveFetcher.class.getName());
 
-	protected final Instance instance;
-	protected final StateFunctor stateFunctor;
+	protected final Tree tree;
+	protected final Future<Void> future;
 	protected int dispatched;
 	protected final Stopwatch stopwatch = new Stopwatch();
 
-	public RecursiveFetcher(Instance instance, final Path path, StateFunctor stateFunctor) {
-		this.instance = instance;
-		this.stateFunctor = stateFunctor;
+	public RecursiveFetcher(Tree tree, final Path path, Future<Void> future) {
+		this.tree = tree;
+		this.future = future;
 		dispatched = 1;
 		process(path);
@@ -37,11 +40,11 @@
 
 	protected void finished() {
-		assert instance.isActive();
+		assert tree.isActive();
 		log.info("recursively fetched in " + stopwatch);
-		stateFunctor.call();
+		future.pass(null);
 	}
 
 	protected void process(final Path path) {
-		assert instance.isActive();
+		assert tree.isActive();
 		if (path == null || !path.isResolved()) {
 			log.warn("path " + path + " is not resolved - skipping");
@@ -55,7 +58,7 @@
 				if (childPath.isResolved() && getInfoFromCache(childPath) != null) {
 					++dispatched;
-					instance.dispatch(new RunAt<Instance>() {
+					tree.dispatch(new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
 						@Override
-						public void run() {
+						protected void runAt() {
 							fetch(childPath);
 						}
@@ -64,8 +67,8 @@
 				}
 				++dispatched;
-				instance.resolve(childPath, new Future<Path>(Logging.logger(log, "resolve", RecursiveFetcher.this)) {
+				tree.resolve(childPath, new FutureHandler<Path>(Logging.logger(log, "resolve", RecursiveFetcher.this)) {
 					@Override
 					protected void result(Path result) {
-						assert instance.isActive();
+						assert tree.isActive();
 						fetch(result);
 					}
@@ -80,5 +83,6 @@
 
 	protected void fetch(final Path path) {
-		instance.fetchValues(path, new StateFunctor() {
+		tree.get(path, Mode.FETCH, new Future<Object>() {
+
 			@Override
 			public void handle(FramsticksException e) {
@@ -88,5 +92,5 @@
 
 			@Override
-			public void call() {
+			protected void result(Object object) {
 				process(path);
 			}
Index: java/main/src/main/java/com/framsticks/remote/RemoteInstance.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/RemoteInstance.java	(revision 96)
+++ 	(revision )
@@ -1,418 +1,0 @@
-package com.framsticks.remote;
-
-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.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.*;
-import com.framsticks.params.annotations.FramsClassAnnotation;
-import com.framsticks.params.annotations.ParamAnnotation;
-import com.framsticks.params.types.EventParam;
-import com.framsticks.params.types.ProcedureParam;
-import com.framsticks.parsers.MultiParamLoader;
-import com.framsticks.core.Instance;
-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;
-import com.framsticks.util.dispatching.JoinableParent;
-import com.framsticks.util.dispatching.JoinableState;
-import com.framsticks.util.lang.Casting;
-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;
-
-/**
- * @author Piotr Sniegowski
- */
-@FramsClassAnnotation
-public class RemoteInstance extends AbstractInstance implements JoinableParent {
-
-	private final static Logger log = Logger.getLogger(RemoteInstance.class.getName());
-
-	protected ClientConnection connection;
-
-	protected final Set<Pair<Path, Subscription<?>>> subscriptions = new HashSet<>();
-
-	public Pair<Path, Subscription<?>> getSubscription(Path path) {
-		for (Pair<Path, Subscription<?>> s : subscriptions) {
-			if (s.first.matches(path)) {
-				return s;
-			}
-		}
-		return null;
-	}
-
-	public RemoteInstance() {
-	}
-
-	@ParamAnnotation
-	public void setAddress(String address) {
-		setConnection(new ClientConnection(address));
-	}
-
-	@ParamAnnotation
-	public String getAddress() {
-		return connection == null ? "<disconnected>" : connection.getAddress();
-	}
-
-	protected void onProtocolVersionNegotiated() {
-	}
-
-
-	public void setConnection(final ClientConnection connection) {
-		this.connection = connection;
-		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() {
-						onProtocolVersionNegotiated();
-					}
-				});
-			}
-		});
-	}
-
-	@Override
-	public String toString() {
-		assert Dispatching.isThreadSafe();
-		return "remote instance " + getName() + "(" + getAddress() + ")";
-	}
-
-	public final ClientConnection getConnection() {
-		return connection;
-	}
-
-	@Override
-	public void fetchValue(final Path path, final ValueParam param, final StateFunctor stateFunctor) {
-		assert isActive();
-		assert param != null;
-		assert path.isResolved();
-		connection.send(new GetRequest().field(param.getId()).path(path.getTextual()), this, new ResponseCallback<Instance>() {
-			@Override
-			public void process(Response response) {
-				assert isActive();
-				if (!response.getOk()) {
-					stateFunctor.handle(new FramsticksException().msg("failed to fetch value").arg("comment", response.getComment()));
-					return;
-				}
-				try {
-					InstanceUtils.processFetchedValues(path, response.getFiles());
-					stateFunctor.call();
-				} catch (FramsticksException ex) {
-					stateFunctor.handle(ex);
-				}
-			}
-		});
-	}
-
-	protected final Map<String, Set<Future<FramsClass>>> infoRequests = new HashMap<String, Set<Future<FramsClass>>>();
-
-	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) {
-			Future.passOrHandle(f, result, e);
-		}
-	}
-
-	@Override
-	public void fetchInfo(final Path path, final Future<FramsClass> future) {
-
-		final String name = path.getTop().getParam().getContainedTypeName();
-
-		if (infoRequests.containsKey(name)) {
-			infoRequests.get(name).add(future);
-			return;
-		}
-
-		log.debug("issuing info request for " + name);
-		Set<Future<FramsClass>> futures = new HashSet<Future<FramsClass>>();
-		futures.add(future);
-		infoRequests.put(name, futures);
-
-		//TODO: if the info is in the cache, then don't communicate
-		connection.send(new InfoRequest().path(path.getTextual()), this, new ResponseCallback<Instance>() {
-			@Override
-			public void process(Response response) {
-				assert isActive();
-				try {
-					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));
-				}
-			}
-		});
-	}
-
-	@Override
-	public void fetchValues(final Path path, final StateFunctor stateFunctor) {
-		assert isActive();
-		assert path.getTop().getObject() != null;
-
-		log.trace("fetching values for " + path);
-		connection.send(new GetRequest().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 fetch values").arg("comment", response.getComment());
-					}
-					InstanceUtils.processFetchedValues(path, response.getFiles());
-					stateFunctor.call();
-				} catch (FramsticksException e) {
-					stateFunctor.handle(e);
-				}
-			}
-		});
-	}
-
-	@Override
-	public void resolve(final Path path, final Future<Path> future) {
-		InstanceUtils.resolve(path, future);
-	}
-
-	@Override
-	protected void tryRegisterOnChangeEvents(final Path path) {
-		assert isActive();
-		AccessInterface access = InstanceUtils.bindAccess(path);
-		if (!(access instanceof ListAccess)) {
-			return;
-		}
-
-		assert path.size() >= 2;
-		FramsClass underFramsClass = getInfoFromCache(path.getUnder().getParam().getContainedTypeName());
-
-		EventParam changedEvent;
-		try {
-			changedEvent = underFramsClass.getParamEntry(path.getTop().getParam().getId() + "_changed", EventParam.class);
-		} catch (FramsticksException e) {
-			return;
-		}
-
-		log.debug("registering for " + changedEvent);
-		if (getSubscription(path) != null) {
-			return;
-		}
-
-		final Pair<Path, Subscription<?>> temporary = new Pair<>(path, null);
-		subscriptions.add(temporary);
-
-		connection.subscribe(path.getTextual() + "_changed", this, new SubscriptionCallback<Instance>() {
-			@Override
-			public EventCallback subscribed(final Subscription<? super Instance> subscription) {
-				if (subscription == null) {
-					log.error("failed to subscribe for change event for " + path);
-					return null;
-				}
-				log.debug("subscribed for change event for " + path);
-				// subscription.setDispatcher(RemoteInstance.this);
-				RemoteInstance.this.dispatch(new RunAt<Instance>() {
-					@Override
-					public void run() {
-						subscriptions.remove(temporary);
-						subscriptions.add(new Pair<Path, Subscription<?>>(path, subscription));
-					}
-				});
-				return new EventCallback() {
-					@Override
-					public void call(List<File> files) {
-						assert isActive();
-						assert files.size() == 1;
-						MultiParamLoader loader = new MultiParamLoader();
-						loader.setNewSource(files.get(0).getContent());
-						loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
-						ReflectionAccess access = new ReflectionAccess(ListChange.class, FramsClass.build().forClass(ListChange.class));
-						loader.addAccessInterface(access);
-						MultiParamLoader.Status status;
-						try {
-							while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
-								if (status == MultiParamLoader.Status.AfterObject) {
-									AccessInterface accessInterface = loader.getLastAccessInterface();
-									reactToChange(path, (ListChange) accessInterface.getSelected());
-								}
-							}
-						} catch (Exception e) {
-							e.printStackTrace();
-						}
-					}
-				};
-			}
-		});
-	}
-
-	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 = InstanceUtils.bindAccess(path);
-		assert access != null;
-
-		if ((listChange.getAction() == ListChange.Action.Modify) && (listChange.getPosition() == -1)) {
-			final String p = path.getTextual();
-			InstanceUtils.resolveAndFetch(this, p, futureListChanger(listChange, p));
-			return;
-		}
-
-		CompositeParam childParam = Casting.tryCast(CompositeParam.class, access.getParam(listChange.getBestIdentifier()));
-		assert childParam != null;
-		switch (listChange.getAction()) {
-			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>(stateFunctor) {
-			@Override
-			protected void callImpl() {
-				InstanceUtils.bindAccess(path).set((ValueParam) param, value);
-			}
-		});
-	}
-
-	@Override
-	protected void joinableStart() {
-		Dispatching.use(connection, this);
-		super.joinableStart();
-	}
-
-	@Override
-	protected void joinableInterrupt() {
-		Dispatching.drop(connection, this);
-		super.joinableInterrupt();
-	}
-
-	@Override
-	protected void joinableFinish() {
-		super.joinableFinish();
-
-	}
-
-	@Override
-	public void joinableJoin() throws InterruptedException {
-		Dispatching.join(connection);
-		super.joinableJoin();
-	}
-
-	@Override
-	public void childChangedState(Joinable joinable, JoinableState state) {
-		proceedToState(state);
-	}
-
-	@Override
-	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/RemoteTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/RemoteTree.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/remote/RemoteTree.java	(revision 97)
@@ -0,0 +1,397 @@
+package com.framsticks.remote;
+
+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.core.AbstractTree;
+import com.framsticks.core.Mode;
+import com.framsticks.core.TreeOperations;
+import com.framsticks.core.ListChange;
+import com.framsticks.core.Node;
+import com.framsticks.core.Path;
+import com.framsticks.params.*;
+import com.framsticks.params.annotations.AutoAppendAnnotation;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.params.types.EventParam;
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.parsers.MultiParamLoader;
+import com.framsticks.core.Tree;
+import com.framsticks.util.*;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableParent;
+import com.framsticks.util.dispatching.JoinableState;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.dispatching.RunAt;
+import static com.framsticks.core.TreeOperations.*;
+
+import java.util.*;
+
+import javax.annotation.Nonnull;
+
+import org.apache.log4j.Logger;
+
+/**
+ * @author Piotr Sniegowski
+ */
+@FramsClassAnnotation
+public class RemoteTree extends AbstractTree implements JoinableParent {
+
+	private final static Logger log = Logger.getLogger(RemoteTree.class);
+
+	protected ClientSideManagedConnection connection;
+
+	protected final Set<Pair<Path, Subscription<?>>> subscriptions = new HashSet<>();
+
+	public Pair<Path, Subscription<?>> getSubscription(Path path) {
+		for (Pair<Path, Subscription<?>> s : subscriptions) {
+			if (s.first.matches(path)) {
+				return s;
+			}
+		}
+		return null;
+	}
+
+	public RemoteTree() {
+	}
+
+	@ParamAnnotation
+	public void setAddress(String address) {
+		setConnection(Connection.to(new ClientSideManagedConnection(), new Address(address)));
+	}
+
+	@ParamAnnotation
+	public String getAddress() {
+		return connection == null ? "<disconnected>" : connection.getAddress().toString();
+	}
+
+	@AutoAppendAnnotation
+	public void setConnection(final ClientSideManagedConnection connection) {
+		this.connection = connection;
+		// 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, RemoteTree.this);
+		// 		fireRun(exception);
+		// 	}
+		// };
+
+	}
+
+	@Override
+	public String toString() {
+		assert Dispatching.isThreadSafe();
+		return "remote tree " + getName() + "(" + getAddress() + ")";
+	}
+
+	public final ClientSideManagedConnection getConnection() {
+		return connection;
+	}
+
+	@Override
+	public void get(final Path path, final PrimitiveParam<?> param, Mode mode, final Future<Object> future) {
+		assert isActive();
+		assert param != null;
+		assert path.isResolved();
+		//TODO only do that if needed
+		connection.send(new GetRequest().field(param.getId()).path(path.getTextual()), this, new ClientSideResponseFuture(future) {
+			@Override
+			protected void processOk(Response response) {
+				assert isActive();
+				TreeOperations.processFetchedValues(path, response.getFiles());
+				future.pass(bindAccess(path).get(param, Object.class));
+			}
+		});
+	}
+
+	protected final Map<String, Set<Future<FramsClass>>> infoRequests = new HashMap<String, Set<Future<FramsClass>>>();
+
+
+	@Override
+	public void info(final Path path, final Future<FramsClass> future) {
+
+		final String name = path.getTop().getParam().getContainedTypeName();
+
+		if (infoRequests.containsKey(name)) {
+			infoRequests.get(name).add(future);
+			return;
+		}
+
+		log.debug("issuing info request for " + name);
+		final Set<Future<FramsClass>> futures = new HashSet<Future<FramsClass>>();
+		futures.add(future);
+		infoRequests.put(name, futures);
+
+		final Future<FramsClass> compositeFuture = new Future<FramsClass>() {
+
+			@Override
+			public void handle(FramsticksException exception) {
+				assert isActive();
+				infoRequests.remove(name);
+				for (Future<FramsClass> f : futures) {
+					f.handle(exception);
+				}
+			}
+
+			@Override
+			protected void result(FramsClass framsClass) {
+				assert isActive();
+				infoRequests.remove(name);
+				for (Future<FramsClass> f : futures) {
+					f.pass(framsClass);
+				}
+			}
+		};
+
+		//TODO: if the info is in the cache, then don't communicate
+		connection.send(new InfoRequest().path(path.getTextual()), this, new ClientSideResponseFuture(compositeFuture) {
+			@Override
+			protected void processOk(Response response) {
+				assert isActive();
+
+				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 = TreeOperations.processFetchedInfo(RemoteTree.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());
+				}
+				compositeFuture.pass(framsClass);
+			}
+		});
+	}
+
+	@Override
+	public void get(final Path path, Mode mode, final Future<Object> future) {
+		assert isActive();
+		assert path.getTop().getObject() != null;
+
+		log.trace("fetching values for " + path);
+		connection.send(new GetRequest().path(path.getTextual()), this, new ClientSideResponseFuture(future) {
+			@Override
+			protected void processOk(Response response) {
+				assert isActive();
+				TreeOperations.processFetchedValues(path, response.getFiles());
+				future.pass(path.getTopObject());
+			}
+		});
+	}
+
+	@Override
+	public void resolve(final Path path, final Future<Path> future) {
+		TreeOperations.resolve(path, future);
+	}
+
+	@Override
+	protected void tryRegisterOnChangeEvents(final Path path) {
+		assert isActive();
+		AccessInterface access = TreeOperations.bindAccess(path);
+		if (!(access instanceof ListAccess)) {
+			return;
+		}
+
+		assert path.size() >= 2;
+		FramsClass underFramsClass = getInfoFromCache(path.getUnder().getParam().getContainedTypeName());
+
+		EventParam changedEvent;
+		try {
+			changedEvent = underFramsClass.getParamEntry(path.getTop().getParam().getId() + "_changed", EventParam.class);
+		} catch (FramsticksException e) {
+			return;
+		}
+
+		log.debug("registering for " + changedEvent);
+		if (getSubscription(path) != null) {
+			return;
+		}
+
+		final Pair<Path, Subscription<?>> temporary = new Pair<>(path, null);
+		subscriptions.add(temporary);
+
+		connection.subscribe(path.getTextual() + "_changed", this, new SubscriptionCallback<Tree>() {
+			@Override
+			public EventCallback subscribed(final Subscription<? super Tree> subscription) {
+				if (subscription == null) {
+					log.error("failed to subscribe for change event for " + path);
+					return null;
+				}
+				log.debug("subscribed for change event for " + path);
+				// subscription.setDispatcher(RemoteInstance.this);
+				RemoteTree.this.dispatch(new RunAt<Tree>(this) {
+					@Override
+					protected void runAt() {
+						subscriptions.remove(temporary);
+						subscriptions.add(new Pair<Path, Subscription<?>>(path, subscription));
+					}
+				});
+				return new EventCallback() {
+					@Override
+					public void call(List<File> files) {
+						assert isActive();
+						assert files.size() == 1;
+						final MultiParamLoader loader = new MultiParamLoader();
+						loader.setNewSource(files.get(0).getContent());
+						loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
+						loader.addListener(MultiParamLoader.Status.OnComment, new MultiParamLoader.StatusListener() {
+
+							@Override
+							public void onStatusChange() {
+								throw new FramsticksException().msg("multi param loader error").arg("line", loader.getCurrentLine());
+							}
+						});
+						ReflectionAccess access = new ReflectionAccess(ListChange.class, FramsClass.build().forClass(ListChange.class));
+						loader.addAccessInterface(access);
+
+						MultiParamLoader.Status status;
+						while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
+							if (status == MultiParamLoader.Status.AfterObject) {
+								AccessInterface accessInterface = loader.getLastAccessInterface();
+								reactToChange(path, (ListChange) accessInterface.getSelected());
+							}
+						}
+					}
+				};
+			}
+		});
+	}
+
+	protected Future<Path> futureListChanger(final ListChange listChange, final String path) {
+		return new FutureHandler<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 = TreeOperations.bindAccess(path);
+		assert access != null;
+
+		if ((listChange.getAction() == ListChange.Action.Modify) && (listChange.getPosition() == -1)) {
+			final String p = path.getTextual();
+			TreeOperations.resolveAndGet(this, p, futureListChanger(listChange, p));
+			return;
+		}
+
+		CompositeParam childParam = Casting.tryCast(CompositeParam.class, access.getParam(listChange.getBestIdentifier()));
+		assert childParam != null;
+		switch (listChange.getAction()) {
+			case Add: {
+				final String p = path.getTextual() + "/" + childParam.getId();
+				TreeOperations.resolveAndGet(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();
+				TreeOperations.resolveAndGet(this, p, futureListChanger(listChange, p));
+				break;
+			}
+		}
+	}
+
+	@Override
+	public void set(final Path path, final PrimitiveParam<?> param, final Object value, final Future<Integer> future) {
+		assert isActive();
+		final Integer flag = TreeOperations.bindAccess(path).set(param, value);
+
+		log.trace("storing value " + param + " for " + path);
+		//TODO break in passing exception handler is here
+		connection.send(new SetRequest().value(value.toString()).field(param.getId()).path(path.getTextual()), this, new ClientSideResponseFuture(future) {
+			@Override
+			protected void processOk(Response response) {
+				future.pass(flag);
+			}
+		});
+	}
+
+	@Override
+	protected void joinableStart() {
+		Dispatching.use(connection, this);
+		super.joinableStart();
+	}
+
+	@Override
+	protected void joinableInterrupt() {
+		Dispatching.drop(connection, this);
+		super.joinableInterrupt();
+	}
+
+	@Override
+	protected void joinableFinish() {
+		super.joinableFinish();
+
+	}
+
+	@Override
+	public void joinableJoin() throws InterruptedException {
+		Dispatching.join(connection);
+		super.joinableJoin();
+	}
+
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		proceedToState(state);
+	}
+
+	@Override
+	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 ClientSideResponseFuture(future) {
+			@Override
+			protected void processOk(Response response) {
+				assert isActive();
+				// InstanceUtils.processFetchedValues(path, response.getFiles());
+				future.pass(null);
+			}
+		});
+
+	}
+
+	@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)
+++ 	(revision )
@@ -1,112 +1,0 @@
-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/remote/SimulatorTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/SimulatorTree.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/remote/SimulatorTree.java	(revision 97)
@@ -0,0 +1,118 @@
+package com.framsticks.remote;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import static com.framsticks.core.TreeOperations.*;
+import com.framsticks.communication.EventCallback;
+import com.framsticks.communication.File;
+import com.framsticks.communication.util.LoggingSubscriptionCallback;
+import com.framsticks.core.Tree;
+import com.framsticks.core.TreeOperations;
+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.FutureHandler;
+import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
+
+@FramsClassAnnotation
+public class SimulatorTree extends RemoteTree {
+
+	private final static Logger log = Logger.getLogger(SimulatorTree.class);
+
+	protected Path simulator;
+
+	/**
+	 *
+	 */
+	public SimulatorTree() {
+		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);
+	}
+
+	@Override
+	protected void joinableStart() {
+		super.joinableStart();
+
+		dispatch(new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				resolveAndGet(SimulatorTree.this, "/simulator", new FutureHandler<Path>(Logging.logger(log, "failed to resolve simulator node", SimulatorTree.this)) {
+					@Override
+					protected void result(Path path) {
+						assert isActive();
+						simulator = path;
+						fireRun(null);
+						log.info("resolved simulator node");
+
+						EventParam param = TreeOperations.getInfoFromCache(simulator).getParamEntry("running_changed", EventParam.class);
+
+						assert param != null;
+						connection.subscribe(simulator.getTextual() + "/" + param.getId(), SimulatorTree.this, new LoggingSubscriptionCallback<Tree>(log, "server running state change", new EventCallback() {
+							@Override
+							public void call(List<File> files) {
+								//TODO TEH
+								dispatch(new RunAt<Tree>(ThrowExceptionHandler.getInstance()) {
+									@Override
+									protected void runAt() {
+										updateSimulationRunning();
+									}
+								});
+							}
+						}));
+						new PeriodicTask<Tree>(ThrowExceptionHandler.getInstance(), SimulatorTree.this, 1000) {
+							@Override
+							protected void runAt() {
+								updateSimulationRunning();
+								again();
+							}
+						};
+					}
+				});
+			}
+		});
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/running/ExternalProcess.java
===================================================================
--- java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 97)
@@ -26,4 +26,5 @@
 import com.framsticks.util.dispatching.RunAt;
 import com.framsticks.util.dispatching.Thread;
+import com.framsticks.util.dispatching.ThrowExceptionHandler;
 import com.framsticks.util.io.Encoding;
 
@@ -129,8 +130,8 @@
 		}
 
-		readerThread.dispatch(new RunAt<ExternalProcess>() {
+		readerThread.dispatch(new RunAt<ExternalProcess>(ThrowExceptionHandler.getInstance()) {
 
 			@Override
-			public void run() {
+			protected void runAt() {
 				readerTask();
 			}
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 97)
@@ -1,3 +1,5 @@
 package com.framsticks.test;
+
+import org.apache.log4j.Logger;
 
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -7,7 +9,10 @@
 @FramsClassAnnotation(order = {"name", "history", "appendHistory", "resetHistory"})
 public class TestClass {
+	private static final Logger log =
+		Logger.getLogger(TestClass.class);
+
 
 	protected String name = "test";
-	protected String history = "";
+	protected String history = "initial|";
 
 	/**
@@ -45,4 +50,5 @@
 	@ParamAnnotation(paramType = ProcedureParam.class)
 	public int appendHistory(String line) {
+		log.debug("appending '" + line + "'");
 		history = history + line + "|";
 		return history.length();
@@ -51,4 +57,5 @@
 	@ParamAnnotation(paramType = ProcedureParam.class)
 	public void resetHistory() {
+		log.debug("reseting");
 		history = "";
 	}
Index: java/main/src/main/java/com/framsticks/util/AbstractStateFunctor.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/AbstractStateFunctor.java	(revision 96)
+++ 	(revision )
@@ -1,26 +1,0 @@
-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 96)
+++ java/main/src/main/java/com/framsticks/util/FramsticksException.java	(revision 97)
@@ -35,5 +35,5 @@
 	}
 
-	public void getShortMessage(StringBuilder b) {
+	public StringBuilder getShortMessage(StringBuilder b) {
 		if (message != null) {
 			b.append(message);
@@ -50,4 +50,5 @@
 			b.append("(").append(d.build()).append(")");
 		}
+		return b;
 	}
 
Index: java/main/src/main/java/com/framsticks/util/PeriodicTask.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/PeriodicTask.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/PeriodicTask.java	(revision 97)
@@ -2,4 +2,5 @@
 
 import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 import com.framsticks.util.dispatching.Task;
 import com.framsticks.util.dispatching.RunAt;
@@ -13,5 +14,6 @@
 	protected Dispatcher<? super C> dispatcher;
 
-	public PeriodicTask(Dispatcher<? super C> dispatcher, long period) {
+	public PeriodicTask(ExceptionResultHandler handler, Dispatcher<? super C> dispatcher, long period) {
+		super(handler);
 		this.period = period;
 		this.dispatcher = dispatcher;
@@ -21,8 +23,8 @@
 
 	public void again() {
-		dispatcher.dispatch(new Task<C>(period) {
+		dispatcher.dispatch(new Task<C>(handler, period) {
 			@Override
-			public void run() {
-				PeriodicTask.this.run();
+			protected void runAt() {
+				PeriodicTask.this.runAt();
 			}
 		});
Index: java/main/src/main/java/com/framsticks/util/ResourceBuilder.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/ResourceBuilder.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/ResourceBuilder.java	(revision 97)
@@ -35,5 +35,5 @@
 
 	@ParamAnnotation
-	public ResourceBuilder<T>  resource(String resource) {
+	public ResourceBuilder<T> resource(String resource) {
 		this.resource = resource;
 		return stream(getClass().getResourceAsStream(resource));
Index: java/main/src/main/java/com/framsticks/util/StateFunctor.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/StateFunctor.java	(revision 96)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package com.framsticks.util;
-
-import com.framsticks.util.dispatching.ExceptionResultHandler;
-
-/**
- * @author Piotr Sniegowski
- */
-public interface StateFunctor extends ExceptionResultHandler {
-	//TODO RunAt
-	public void call();
-}
Index: java/main/src/main/java/com/framsticks/util/UnaryFunctor.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/UnaryFunctor.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/UnaryFunctor.java	(revision 97)
@@ -5,4 +5,4 @@
  */
 public interface UnaryFunctor <Ret, Arg> {
-		Ret call(Arg arg);
+	Ret call(Arg arg);
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java	(revision 97)
@@ -137,5 +137,7 @@
 		boolean start = false;
 		synchronized (this) {
-			assert !owners.contains(owner);
+			if (owners.contains(owner)) {
+				throw new FramsticksException().msg("owner is already using that joinable").arg("joinable", this).arg("owner", owner);
+			}
 			start = owners.isEmpty();
 			log.debug(owner + " is using " + this);
@@ -164,7 +166,7 @@
 		}
 		if (stop) {
-			Dispatching.dispatcherGuardedInvoke(this, new RunAt<Object>() {
+			Dispatching.dispatcherGuardedInvoke(this, new RunAt<Object>(ThrowExceptionHandler.getInstance()) {
 				@Override
-				public void run() {
+				protected void runAt() {
 					interrupt();
 				}
Index: java/main/src/main/java/com/framsticks/util/dispatching/AtOnceDispatcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/AtOnceDispatcher.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/dispatching/AtOnceDispatcher.java	(revision 97)
@@ -21,5 +21,5 @@
 	@Override
 	public final void dispatch(RunAt<? extends C> runnable) {
-		runnable.run();
+		runnable.runAt();
 	}
 
Index: java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 97)
@@ -4,5 +4,4 @@
 
 import com.framsticks.util.FramsticksException;
-import com.framsticks.util.StateFunctor;
 
 /**
@@ -18,18 +17,8 @@
 	public static <C> void dispatchIfNotActive(Dispatcher<C> dispatcher, RunAt<? extends C> runnable) {
 		if (dispatcher.isActive()) {
-			runnable.run();
+			runnable.runAt();
 			return;
 		}
 		dispatcher.dispatch(runnable);
-	}
-
-	//TODO RunAt StateFunctor
-	public static <C> void dispatchOk(Dispatcher<C> dispatcher, final StateFunctor stateFunctor) {
-		dispatcher.dispatch(new RunAt<C>() {
-			@Override
-			public void run() {
-				stateFunctor.call();
-			}
-		});
 	}
 
@@ -40,7 +29,7 @@
 
 	public static <P, C> void invokeDispatch(Dispatcher<P> dispatcher, final Dispatcher<C> finalDispatcher, final RunAt<C> runnable) {
-		dispatcher.dispatch(new RunAt<P>() {
+		dispatcher.dispatch(new RunAt<P>(runnable) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				finalDispatcher.dispatch(runnable);
 			}
@@ -49,4 +38,5 @@
 
 	public static void sleep(double seconds) {
+		log.debug("sleeping");
 		try {
 			java.lang.Thread.sleep((long) (seconds * 1000));
@@ -54,4 +44,5 @@
 
 		}
+		log.debug("slept");
 	}
 
@@ -62,5 +53,5 @@
 			return;
 		}
-		runnable.run();
+		runnable.runAt();
 	}
 
@@ -95,7 +86,7 @@
 
 	public static void childChangedState(final JoinableParent parent, final Joinable joinable, final JoinableState state) {
-		dispatcherGuardedInvoke(joinable, new RunAt<Object>() {
+		dispatcherGuardedInvoke(joinable, new RunAt<Object>(ThrowExceptionHandler.getInstance()) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				log.debug("joinable " + joinable + " is notifying parent " + parent + " about change to " + state);
 				parent.childChangedState(joinable, state);
@@ -140,9 +131,11 @@
 		 */
 		public QueryRunner(Query<T> query) {
+			//TODO TEH
+			super(ThrowExceptionHandler.getInstance());
 			this.query = query;
 		}
 
 		@Override
-		public void run() {
+		protected void runAt() {
 			result = query.get();
 			synchronized (this) {
@@ -206,7 +199,7 @@
 	public static <C> void synchronize(Dispatcher<C> dispatcher, double seconds) {
 		final Waiter waiter = new Waiter(seconds);
-		dispatcher.dispatch(new RunAt<C>() {
+		dispatcher.dispatch(new RunAt<C>(ThrowExceptionHandler.getInstance()) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				waiter.pass();
 			}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Future.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Future.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Future.java	(revision 97)
@@ -7,14 +7,4 @@
  */
 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);
@@ -28,19 +18,4 @@
 	}
 
-	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/FutureHandler.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/FutureHandler.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/util/dispatching/FutureHandler.java	(revision 97)
@@ -0,0 +1,19 @@
+package com.framsticks.util.dispatching;
+
+import com.framsticks.util.FramsticksException;
+
+public abstract class FutureHandler<T> extends Future<T> {
+
+	protected final ExceptionResultHandler handler;
+
+	public FutureHandler(ExceptionResultHandler handler) {
+		assert handler != null;
+		this.handler = handler;
+	}
+
+	@Override
+	public final void handle(FramsticksException exception) {
+		handler.handle(exception);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/dispatching/JoinableCollection.java	(revision 97)
@@ -1,4 +1,6 @@
 package com.framsticks.util.dispatching;
 
+import java.util.AbstractCollection;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -42,4 +44,19 @@
 		if (this.state.equals(JoinableState.RUNNING)) {
 			Dispatching.use(joinable, this);
+		}
+	}
+
+	public synchronized void remove(T joinable) {
+		if (this.state.ordinal() > JoinableState.RUNNING.ordinal()) {
+			throw new FramsticksException().msg("failed to remote joinable - collection is passed running state").arg("joinable", joinable).arg("collection", this);
+		}
+		if (!joinables.contains(joinable)) {
+			throw new FramsticksException().msg("joinable is not observed").arg("joinable", joinable).arg("in", this);
+		}
+
+		joinables.remove(joinable);
+
+		if (this.state.equals(JoinableState.RUNNING)) {
+			Dispatching.drop(joinable, this);
 		}
 	}
@@ -140,3 +157,31 @@
 	}
 
+	public Collection<T> asCollection() {
+		return new AbstractCollection<T>() {
+
+			@Override
+			public Iterator<T> iterator() {
+				return JoinableCollection.this.iterator();
+			}
+
+			@Override
+			public int size() {
+				return JoinableCollection.this.size();
+			}
+
+			@Override
+			public boolean add(T joinable) {
+				JoinableCollection.this.add(joinable);
+				return true;
+			}
+
+			@SuppressWarnings("unchecked")
+			@Override
+			public boolean remove(Object joinable) {
+				JoinableCollection.this.remove((T) joinable);
+				return true;
+			}
+		};
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/RunAt.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/RunAt.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/dispatching/RunAt.java	(revision 97)
@@ -1,11 +1,31 @@
 package com.framsticks.util.dispatching;
 
-public abstract class RunAt<C> implements java.lang.Runnable {
+import com.framsticks.util.FramsticksException;
 
-	public RunAt() {
+public abstract class RunAt<C> implements ExceptionResultHandler, Runnable {
+
+	protected final ExceptionResultHandler handler;
+
+	public RunAt(ExceptionResultHandler handler) {
+		assert handler != null;
+		this.handler = handler;
 	}
 
-	public RunAt(Dispatcher<? super C> dispatcher) {
-		dispatcher.dispatch(this);
+	protected abstract void runAt();
+
+	public final void run() {
+		try {
+			runAt();
+		} catch (FramsticksException e) {
+			handle(e);
+		}
 	}
+
+
+
+	@Override
+	public final void handle(FramsticksException exception) {
+		handler.handle(exception);
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/Task.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Task.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Task.java	(revision 97)
@@ -8,9 +8,11 @@
 	protected final long moment;
 
-	public Task() {
+	public Task(ExceptionResultHandler handler) {
+		super(handler);
 		moment = System.currentTimeMillis();
 	}
 
-	public Task(long moment) {
+	public Task(ExceptionResultHandler handler, long moment) {
+		super(handler);
 		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 96)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 97)
@@ -15,5 +15,5 @@
 public class Thread<C> extends AbstractJoinable implements Dispatcher<C> {
 
-	private static final Logger log = Logger.getLogger(Thread.class.getName());
+	private static final Logger log = Logger.getLogger(Thread.class);
 
 	protected final java.lang.Thread thread;
@@ -73,5 +73,5 @@
 			}
 			try {
-				task.run();
+				task.runAt();
 			} catch (Exception e) {
 				if (exceptionHandler != null) {
@@ -119,8 +119,8 @@
 	public void dispatch(final RunAt<? extends C> runnable) {
 		if (!(runnable instanceof Task)) {
-			enqueueTask(new Task<C>() {
+			enqueueTask(new Task<C>(runnable) {
 				@Override
-				public void run() {
-					runnable.run();
+				protected void runAt() {
+					runnable.runAt();
 				}
 			});
Index: java/main/src/main/java/com/framsticks/util/dispatching/ThrowExceptionHandler.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/ThrowExceptionHandler.java	(revision 97)
+++ java/main/src/main/java/com/framsticks/util/dispatching/ThrowExceptionHandler.java	(revision 97)
@@ -0,0 +1,24 @@
+package com.framsticks.util.dispatching;
+
+import com.framsticks.util.FramsticksException;
+
+public class ThrowExceptionHandler implements ExceptionResultHandler {
+
+	private static final ThrowExceptionHandler instance = new ThrowExceptionHandler();
+
+	private ThrowExceptionHandler() {
+	}
+
+	@Override
+	public final void handle(FramsticksException exception) {
+		throw exception;
+	}
+
+	/**
+	 * @return the instance
+	 */
+	public static ThrowExceptionHandler getInstance() {
+		return instance;
+	}
+
+}
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)
+++ 	(revision )
@@ -1,30 +1,0 @@
-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/io/Encoding.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/io/Encoding.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/io/Encoding.java	(revision 97)
@@ -7,5 +7,6 @@
 	protected static final Charset defaultCharset = Charset.forName("UTF-8");
 
-	protected static final Charset framsticksCharset = Charset.forName("ISO-8859-1");
+	protected static final Charset framsticksCharset = Charset.forName("UTF-8");
+	//Charset.forName("ISO-8859-1");
 
 
Index: java/main/src/main/java/com/framsticks/util/lang/Strings.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Strings.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/util/lang/Strings.java	(revision 97)
@@ -26,6 +26,10 @@
 
 	public static String toStringNullProof(Object object) {
+		return toStringNullProof(object, "");
+	}
+
+	public static String toStringNullProof(Object object, String def) {
 		if (object == null) {
-			return "";
+			return def;
 		}
 		return object.toString();
@@ -56,3 +60,13 @@
 		return input.substring(0, 1).toLowerCase() + input.substring(1);
 	}
+
+	public static String commonPrefix(String a, String b) {
+		int length = Math.min(a.length(), b.length());
+		int i = 0;
+		while ((i < length) && (a.charAt(i) == b.charAt(i))) {
+			++i;
+		}
+		return a.substring(0, i);
+	}
+
 }
Index: java/main/src/main/resources/configs/console.xml
===================================================================
--- java/main/src/main/resources/configs/console.xml	(revision 97)
+++ java/main/src/main/resources/configs/console.xml	(revision 97)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Framsticks>
+	<import class="com.framsticks.gui.console.DirectConsole" />
+	<import class="com.framsticks.communication.ClientSideRawConnection" />
+	<DirectConsole>
+		<ClientSideRawConnection address="localhost:9009" />
+	</DirectConsole>
+</Framsticks>
Index: java/main/src/main/resources/configs/framsticks.xml
===================================================================
--- java/main/src/main/resources/configs/framsticks.xml	(revision 96)
+++ java/main/src/main/resources/configs/framsticks.xml	(revision 97)
@@ -1,29 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Framsticks>
-	<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>
-		<SimulatorInstance name="localhost:9009" address="localhost:9009">
-			<ModelPackage />
-		</SimulatorInstance>
-		<ObjectInstance name="model">
-			<ModelBuilder resource="/examples/f0_example.txt" />
-		</ObjectInstance>
-		<ObjectInstance name="f0schema">
-			<SchemaBuilder />
-		</ObjectInstance>
-		<RemoteInstance name="remote" address="localhost:9007" />
-	</Browser>
-	<Server name="server" port="9007">
-		<ObjectInstance name="test">
-			<TestClass />
-		</ObjectInstance>
-	</Server>
+	<import class="com.framsticks.gui.console.ManagedConsole" />
+	<import class="com.framsticks.remote.RemoteTree" />
+	<ManagedConsole>
+		<RemoteTree name="remote" address="localhost:9009" />
+	</ManagedConsole>
+
+	<!-- <import class="com.framsticks.gui.console.DirectConsole" /> -->
+	<!-- <import class="com.framsticks.communication.ClientSideRawConnection" /> -->
+	<!-- <DirectConsole> -->
+	<!-- 	<ClientSideRawConnection address="localhost:9009" /> -->
+	<!-- </DirectConsole> -->
+
+	<!-- <import class="com.framsticks.gui.Browser" /> -->
+	<!-- <import class="com.framsticks.remote.RemoteTree" /> -->
+	<!-- <import class="com.framsticks.remote.SimulatorTree" /> -->
+	<!-- <import class="com.framsticks.model.ModelPackage" /> -->
+	<!-- <import class="com.framsticks.model.ModelBuilder" /> -->
+	<!-- <import class="com.framsticks.model.f0.SchemaBuilder" /> -->
+	<!-- <import class="com.framsticks.core.ObjectTree" /> -->
+	<!-- <import class="com.framsticks.hosting.Server" /> -->
+	<!-- <import class="com.framsticks.test.TestClass" /> -->
+	<!-- <Browser> -->
+	<!-- 	<SimulatorTree name="localhost:9009" address="localhost:9009"> -->
+	<!-- 		<ModelPackage /> -->
+	<!-- 	</SimulatorTree> -->
+	<!-- 	<ObjectTree name="model"> -->
+	<!-- 		<ModelBuilder resource="/examples/f0_example.txt" /> -->
+	<!-- 	</ObjectTree> -->
+	<!-- 	<ObjectTree name="f0schema"> -->
+	<!-- 		<SchemaBuilder /> -->
+	<!-- 	</ObjectTree> -->
+	<!-- 	<RemoteTree name="remote" address="localhost:9007" /> -->
+	<!-- </Browser> -->
+	<!-- <Server name="server" port="9007"> -->
+	<!-- 	<ObjectTree name="test"> -->
+	<!-- 		<TestClass /> -->
+	<!-- 	</ObjectTree> -->
+	<!-- </Server> -->
 </Framsticks>
Index: java/main/src/main/resources/configs/log4j.properties
===================================================================
--- java/main/src/main/resources/configs/log4j.properties	(revision 96)
+++ java/main/src/main/resources/configs/log4j.properties	(revision 97)
@@ -31,6 +31,4 @@
 # 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.params.ReflectionAccess=TRACE
@@ -49,5 +47,4 @@
 #log4j.logger.com.framsticks.gui.Browser=DEBUG
 #log4j.logger.com.framsticks.gui.EndpointAtFrame=DEBUG
-#log4j.logger.com.framsticks.remote.RemoteInstance=DEBUG
 #log4j.logger.com.framsticks.gui.TreeNode=DEBUG
 #log4j.logger.com.framsticks.gui.components.CheckBox=DEBUG
Index: java/main/src/test/java/com/framsticks/core/ObjectInstanceTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/core/ObjectInstanceTest.java	(revision 96)
+++ 	(revision )
@@ -1,91 +1,0 @@
-package com.framsticks.core;
-
-import java.util.ArrayList;
-
-import org.testng.annotations.BeforeClass;
-// import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.framsticks.model.Joint;
-import com.framsticks.model.Model;
-import com.framsticks.model.ModelBuilder;
-import com.framsticks.model.f0.Schema;
-import com.framsticks.model.f0.SchemaBuilder;
-import com.framsticks.test.TestConfiguration;
-import com.framsticks.util.dispatching.Dispatching;
-import com.framsticks.util.dispatching.Monitor;
-import com.framsticks.util.dispatching.RunAt;
-import com.framsticks.params.AccessInterface;
-import com.framsticks.params.ReflectionAccess;
-import com.framsticks.params.types.FloatParam;
-
-import static com.framsticks.core.InstanceUtils.*;
-
-
-import static org.fest.assertions.Assertions.*;
-
-@Test
-public class ObjectInstanceTest extends TestConfiguration {
-
-	private Model model;
-	private Schema schema;
-	private ObjectInstance instance;
-	private Monitor monitor;
-
-	@BeforeClass
-	public void setUp() {
-		schema = new SchemaBuilder().stream(Schema.getDefaultDefinitionAsStream()).finish();
-		assertThat(schema.getFramsClasses().size()).isEqualTo(5);
-		assertThat(schema.getNeuroClasses().size()).isEqualTo(21);
-	}
-
-	@Test
-	public void loadModel() {
-		model = new ModelBuilder().schema(schema).stream(ObjectInstanceTest.class.getResourceAsStream("/parsers/f0_example.txt")).finish();
-
-		assertThat(model.getJoints().size()).isEqualTo(2);
-	}
-
-
-	@Test(dependsOnMethods = "loadModel", timeOut = 2000)
-	public void startInstance() {
-		instance = new ObjectInstance();
-		instance.takeAllFrom(schema.getRegistry());
-
-		instance.setRootObject(model);
-
-		monitor = new Monitor(instance);
-		monitor.use();
-
-		assertThat(Dispatching.get(instance, new Dispatching.Query<String>() {
-				@Override
-				public String get() {
-					return instance.getRootObject(Model.class).getParts().get(2).info;
-				}
-			})).isEqualTo("bla");
-
-		instance.dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				assertThat(instance.getRootObject(Model.class).getNeuroDefinitions().get(2).details).isEqualTo("G");
-
-				Path path = Path.to(instance, "/");
-				assertThat(path.isResolved());
-				AccessInterface access = InstanceUtils.bindAccess(path);
-				assertThat(access.get("se", Double.class)).isEqualTo(1.0);
-
-				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");
-			}
-		});
-	}
-
-	@Test(dependsOnMethods = "startInstance", timeOut = 2000)
-	public void stoptInstance() {
-		monitor.useFor(1.0).drop().join();
-	}
-}
Index: java/main/src/test/java/com/framsticks/core/ObjectTreeTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/core/ObjectTreeTest.java	(revision 97)
+++ java/main/src/test/java/com/framsticks/core/ObjectTreeTest.java	(revision 97)
@@ -0,0 +1,91 @@
+package com.framsticks.core;
+
+import java.util.ArrayList;
+
+import org.testng.annotations.BeforeClass;
+// import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.framsticks.model.Joint;
+import com.framsticks.model.Model;
+import com.framsticks.model.ModelBuilder;
+import com.framsticks.model.f0.Schema;
+import com.framsticks.model.f0.SchemaBuilder;
+import com.framsticks.test.TestConfiguration;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Monitor;
+import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.params.AccessInterface;
+import com.framsticks.params.ReflectionAccess;
+import com.framsticks.params.types.FloatParam;
+
+import static com.framsticks.core.TreeOperations.*;
+
+
+import static org.fest.assertions.Assertions.*;
+
+@Test
+public class ObjectTreeTest extends TestConfiguration {
+
+	private Model model;
+	private Schema schema;
+	private ObjectTree tree;
+	private Monitor monitor;
+
+	@BeforeClass
+	public void setUp() {
+		schema = new SchemaBuilder().stream(Schema.getDefaultDefinitionAsStream()).finish();
+		assertThat(schema.getFramsClasses().size()).isEqualTo(5);
+		assertThat(schema.getNeuroClasses().size()).isEqualTo(21);
+	}
+
+	@Test
+	public void loadModel() {
+		model = new ModelBuilder().schema(schema).stream(ObjectTreeTest.class.getResourceAsStream("/parsers/f0_example.txt")).finish();
+
+		assertThat(model.getJoints().size()).isEqualTo(2);
+	}
+
+
+	@Test(dependsOnMethods = "loadModel", timeOut = 2000)
+	public void startTree() {
+		tree = new ObjectTree();
+		tree.takeAllFrom(schema.getRegistry());
+
+		tree.setRootObject(model);
+
+		monitor = new Monitor(tree);
+		monitor.use();
+
+		assertThat(Dispatching.get(tree, new Dispatching.Query<String>() {
+				@Override
+				public String get() {
+					return tree.getRootObject(Model.class).getParts().get(2).info;
+				}
+			})).isEqualTo("bla");
+
+		tree.dispatch(new RunAt<Tree>(failOnException) {
+			@Override
+			protected void runAt() {
+				assertThat(tree.getRootObject(Model.class).getNeuroDefinitions().get(2).details).isEqualTo("G");
+
+				Path path = Path.to(tree, "/");
+				assertThat(path.isResolved());
+				AccessInterface access = TreeOperations.bindAccess(path);
+				assertThat(access.get("se", Double.class)).isEqualTo(1.0);
+
+				assertThat(bindAccess(tree, "/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getDef(Double.class)).isEqualTo(1.0);
+				assertThat(bindAccess(tree, "/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getMax(Double.class)).isEqualTo(999.0);
+				assertThat(bindAccess(tree, "/parts/2")).isInstanceOf(ReflectionAccess.class);
+				assertThat(Path.to(tree, "/neurodefs").getTopObject()).isInstanceOf(ArrayList.class);
+				assertThat(Path.to(tree, "/joints/1").getTopObject()).isInstanceOf(Joint.class);
+				assertThat(bindAccess(tree, "/parts/2").get("i", String.class)).isEqualTo("bla");
+			}
+		});
+	}
+
+	@Test(dependsOnMethods = "startTree", timeOut = 2000)
+	public void stopTree() {
+		monitor.useFor(1.0).drop().join();
+	}
+}
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 97)
@@ -16,9 +16,9 @@
 		// 				public void result(Path result, Exception e) {
 		// 					if (e != null) {
-		// 						log.error("failed to load file instance " + FileInstance.this + ": " + e);
+		// 						log.error("failed to load file: " + e);
 		// 						fireRun(e);
 		// 						return;
 		// 					}
-		// 					log.info("loaded file instance " + FileInstance.this);
+		// 					log.info("loaded file");
 		// 					fireRun(null);
 		// 				}
Index: java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 96)
+++ java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 97)
@@ -4,6 +4,4 @@
 
 import org.apache.log4j.Logger;
-import org.fest.swing.core.Robot;
-import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
 import org.fest.swing.edt.GuiQuery;
 import org.fest.swing.fixture.FrameFixture;
@@ -11,28 +9,17 @@
 import org.testng.annotations.Test;
 
-import com.framsticks.test.MonitorBasedTest;
+
+import org.fest.swing.edt.GuiActionRunner;
+
 import com.framsticks.util.dispatching.Joinable;
 
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.swing.edt.GuiActionRunner.executeInEDT;
-import static org.fest.swing.core.BasicRobot.robotWithNewAwtHierarchy;
-import org.fest.swing.edt.GuiActionRunner;
-
 @Test
-public abstract class BrowserBaseTest extends MonitorBasedTest {
+public abstract class BrowserBaseTest extends GuiTest {
 
 	private static final Logger log = Logger.getLogger(BrowserTest.class);
 
 	protected Browser browser;
-	protected static Robot robot;
 	protected FrameFixture frame;
 	protected JTreeFixture tree;
-
-	static {
-		FailOnThreadViolationRepaintManager.install();
-		assertThat(executeInEDT()).isTrue();
-
-		robot = robotWithNewAwtHierarchy();
-	}
 
 	@Override
@@ -64,7 +51,4 @@
 	}
 
-	protected void waitForIdle() {
-		robot.waitForIdle();
-	}
 
 }
Index: java/main/src/test/java/com/framsticks/gui/BrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 96)
+++ java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 97)
@@ -3,4 +3,6 @@
 import static org.fest.assertions.Assertions.assertThat;
 import static org.fest.swing.edt.GuiActionRunner.execute;
+
+import java.awt.event.KeyEvent;
 
 
@@ -10,5 +12,6 @@
 
 import com.framsticks.model.ModelPackage;
-import com.framsticks.remote.SimulatorInstance;
+import com.framsticks.remote.SimulatorTree;
+import com.framsticks.util.dispatching.Dispatching;
 
 public class BrowserTest extends BrowserBaseTest {
@@ -16,5 +19,5 @@
 	private static final Logger log = Logger.getLogger(BrowserTest.class);
 
-	SimulatorInstance localhost;
+	SimulatorTree localhost;
 
 	@Override
@@ -22,18 +25,19 @@
 		browser = new Browser();
 
-		localhost = new SimulatorInstance();
+		localhost = new SimulatorTree();
 		localhost.setName("localhost");
 		localhost.setAddress("localhost:9009");
 		localhost.usePackage(new ModelPackage());
 
-		browser.addInstance(localhost);
+		browser.addTree(localhost);
 
 	}
 
-	@Test(timeOut = 10000)
+	@Test(timeOut = 30000)
 	public void testShow() {
 		log.info("testing");
 		tree.clickRow(0).expandRow(0);
 		robot.waitForIdle();
+
 		tree.clickRow(1).expandRow(1);
 		robot.waitForIdle();
@@ -47,7 +51,19 @@
 		});
 
+
 		clickAndExpandPath("localhost/simulator/genepools");
 		clickAndExpandPath("localhost/simulator/genepools/groups");
 		clickAndExpandPath("localhost/simulator/genepools/groups/Genotypes");
+		clickAndExpandPath("localhost/simulator/genepools/groups/Genotypes/genotypes");
+		Dispatching.sleep(2.0);
+		clickAndExpandPath("localhost/simulator/genepools/groups/Genotypes/genotypes");
+		robot.pressAndReleaseKey(KeyEvent.VK_J);
+		waitForIdle();
+		Dispatching.sleep(2.0);
+
+		frame.panel("Genotype").panel("name").textBox("value").enterText("-Żółw");
+		clickButton(frame.panel("Genotype").button("apply"));
+
+		Dispatching.sleep(1.0);
 	}
 
Index: java/main/src/test/java/com/framsticks/gui/GuiTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/GuiTest.java	(revision 97)
+++ java/main/src/test/java/com/framsticks/gui/GuiTest.java	(revision 97)
@@ -0,0 +1,42 @@
+package com.framsticks.gui;
+
+import org.fest.swing.core.Robot;
+import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
+import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiTask;
+import org.fest.swing.fixture.JButtonFixture;
+import org.testng.annotations.Test;
+
+import com.framsticks.test.MonitorBasedTest;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.swing.edt.GuiActionRunner.executeInEDT;
+import static org.fest.swing.core.BasicRobot.robotWithNewAwtHierarchy;
+
+@Test
+public abstract class GuiTest extends MonitorBasedTest {
+
+	protected static Robot robot;
+
+	static {
+		FailOnThreadViolationRepaintManager.install();
+		assertThat(executeInEDT()).isTrue();
+
+		robot = robotWithNewAwtHierarchy();
+	}
+
+	protected void waitForIdle() {
+		robot.waitForIdle();
+	}
+
+	protected void clickButton(final JButtonFixture button) {
+
+		// button.click();
+
+		GuiActionRunner.execute(new GuiTask() {
+			@Override
+			protected void executeInEDT() throws Throwable {
+				button.component().doClick();
+			}
+		});
+	}
+}
Index: java/main/src/test/java/com/framsticks/gui/ObjectInstanceBrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/ObjectInstanceBrowserTest.java	(revision 96)
+++ 	(revision )
@@ -1,54 +1,0 @@
-package com.framsticks.gui;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-import org.testng.annotations.Test;
-
-import com.framsticks.core.Instance;
-import com.framsticks.core.ObjectInstance;
-import com.framsticks.model.Model;
-import com.framsticks.params.types.FloatParam;
-import com.framsticks.parsers.XmlLoader;
-import com.framsticks.util.dispatching.RunAt;
-
-import static com.framsticks.core.InstanceUtils.*;
-
-@Test
-public class ObjectInstanceBrowserTest extends BrowserBaseTest {
-
-	ObjectInstance instance;
-
-	@Override
-	protected void configureBrowser() {
-		browser = new XmlLoader().load(Browser.class, getClass().getResourceAsStream("/configs/ObjectInstanceBrowserTest.xml"));
-
-		assertThat(browser.getInstances().size()).isEqualTo(1);
-		assertThat(browser.getInstances().get("model")).isInstanceOf(ObjectInstance.class);
-
-		instance = (ObjectInstance) browser.getInstances().get("model");
-	}
-
-	@Test(timeOut = 10000)
-	public void testShow() {
-		instance.dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				assertThat(instance.getRootObject()).isInstanceOf(Model.class);
-			}
-		});
-
-		clickAndExpandPath("model");
-		clickAndExpandPath("model/parts");
-		clickAndExpandPath("model/parts/2");
-
-		instance.dispatch(new RunAt<Instance>() {
-			@Override
-			public void run() {
-				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/ObjectTreeBrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/ObjectTreeBrowserTest.java	(revision 97)
+++ java/main/src/test/java/com/framsticks/gui/ObjectTreeBrowserTest.java	(revision 97)
@@ -0,0 +1,54 @@
+package com.framsticks.gui;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.core.Tree;
+import com.framsticks.core.ObjectTree;
+import com.framsticks.model.Model;
+import com.framsticks.params.types.FloatParam;
+import com.framsticks.parsers.XmlLoader;
+import com.framsticks.util.dispatching.RunAt;
+
+import static com.framsticks.core.TreeOperations.*;
+
+@Test
+public class ObjectTreeBrowserTest extends BrowserBaseTest {
+
+	ObjectTree tree;
+
+	@Override
+	protected void configureBrowser() {
+		browser = new XmlLoader().load(Browser.class, getClass().getResourceAsStream("/configs/ObjectTreeBrowserTest.xml"));
+
+		assertThat(browser.getTrees().size()).isEqualTo(1);
+		assertThat(browser.getTrees().get("model")).isInstanceOf(ObjectTree.class);
+
+		tree = (ObjectTree) browser.getTrees().get("model");
+	}
+
+	@Test(timeOut = 10000)
+	public void testShow() {
+		tree.dispatch(new RunAt<Tree>(failOnException) {
+			@Override
+			protected void runAt() {
+				assertThat(tree.getRootObject()).isInstanceOf(Model.class);
+			}
+		});
+
+		clickAndExpandPath("model");
+		clickAndExpandPath("model/parts");
+		clickAndExpandPath("model/parts/2");
+
+		tree.dispatch(new RunAt<Tree>(failOnException) {
+			@Override
+			protected void runAt() {
+				assertThat(bindAccess(tree, "/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 96)
+++ java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 97)
@@ -7,6 +7,6 @@
 import org.testng.annotations.Test;
 
-import com.framsticks.core.Instance;
-import com.framsticks.core.ObjectInstance;
+import com.framsticks.core.Tree;
+import com.framsticks.core.ObjectTree;
 import com.framsticks.params.AccessInterface;
 import com.framsticks.params.FramsClass;
@@ -15,11 +15,12 @@
 import com.framsticks.parsers.XmlLoader;
 import com.framsticks.test.TestClass;
+// import com.framsticks.util.dispatching.Dispatching;
 import com.framsticks.util.dispatching.RunAt;
-import static com.framsticks.core.InstanceUtils.*;
+import static com.framsticks.core.TreeOperations.*;
 
 @Test
 public class ProcedureBrowserTest extends BrowserBaseTest {
 
-	ObjectInstance instance;
+	ObjectTree tree;
 
 	@Override
@@ -27,16 +28,16 @@
 		browser = new XmlLoader().load(Browser.class, getClass().getResourceAsStream("/configs/ProcedureBrowserTest.xml"));
 
-		assertThat(browser.getInstances().size()).isEqualTo(1);
-		assertThat(browser.getInstances().get("test")).isInstanceOf(ObjectInstance.class);
+		assertThat(browser.getTrees().size()).isEqualTo(1);
+		assertThat(browser.getTrees().get("test")).isInstanceOf(ObjectTree.class);
 
-		instance = (ObjectInstance) browser.getInstances().get("test");
+		tree = (ObjectTree) browser.getTrees().get("test");
 	}
 
 	@Test(timeOut = 10000)
 	public void testShow() {
-		instance.dispatch(new RunAt<Instance>() {
+		tree.dispatch(new RunAt<Tree>(failOnException) {
 			@Override
-			public void run() {
-				assertThat(instance.getRootObject()).isInstanceOf(TestClass.class);
+			protected void runAt() {
+				assertThat(tree.getRootObject()).isInstanceOf(TestClass.class);
 			}
 		});
@@ -44,8 +45,8 @@
 		clickAndExpandPath("test");
 
-		instance.dispatch(new RunAt<Instance>() {
+		tree.dispatch(new RunAt<Tree>(failOnException) {
 			@Override
-			public void run() {
-				assertThat(bindAccess(instance, "/").getFramsClass().getParam("history")).isInstanceOf(StringParam.class);
+			protected void runAt() {
+				assertThat(bindAccess(tree, "/").getFramsClass().getParam("history")).isInstanceOf(StringParam.class);
 			}
 		});
@@ -53,8 +54,8 @@
 		// monitor.useFor(4.0);
 
-		instance.dispatch(new RunAt<Instance>() {
+		tree.dispatch(new RunAt<Tree>(failOnException) {
 			@Override
-			public void run() {
-				AccessInterface access = bindAccess(instance, "/");
+			protected void runAt() {
+				AccessInterface access = bindAccess(tree, "/");
 				assertThat(access).isInstanceOf(ReflectionAccess.class);
 				FramsClass framsClass = access.getFramsClass();
@@ -65,28 +66,30 @@
 				assertThat(framsClass.getParam(3).getId()).isEqualTo("resetHistory");
 
-				assertThat(access.get("history", String.class)).isEqualTo("");
+				assertThat(access.get("history", String.class)).isEqualTo("initial|");
 			}
 		});
 
 		// frame.panel("TestClass");
-		JPanelFixture appendHistory = frame.panel("TestClass").panel("appendHistory");
-		appendHistory.panel("arg0").textBox("value").enterText("argument");
-		appendHistory.button("call").click();
+		final JPanelFixture appendHistory = frame.panel("TestClass").panel("appendHistory");
+		appendHistory.panel("arg0").textBox("value").enterText("Żółw");
+		assertThat(appendHistory.panel("arg0").textBox("value").text()).isEqualTo("Żółw");
+		clickButton(appendHistory.button("call"));
 		waitForIdle();
 
-		instance.dispatch(new RunAt<Instance>() {
+
+		tree.dispatch(new RunAt<Tree>(failOnException) {
 			@Override
-			public void run() {
-				assertThat(bindAccess(instance, "/").get("history", String.class)).isEqualTo("argument|");
+			protected void runAt() {
+				assertThat(bindAccess(tree, "/").get("history", String.class)).isEqualTo("initial|Żółw|");
 			}
 		});
 
-		frame.panel("TestClass").panel("resetHistory").button("call").click();
+		clickButton(frame.panel("TestClass").panel("resetHistory").button("call"));
 		waitForIdle();
 
-		instance.dispatch(new RunAt<Instance>() {
+		tree.dispatch(new RunAt<Tree>(failOnException) {
 			@Override
-			public void run() {
-				assertThat(bindAccess(instance, "/").get("history", String.class)).isEqualTo("");
+			protected void runAt() {
+				assertThat(bindAccess(tree, "/").get("history", String.class)).isEqualTo("");
 			}
 		});
Index: java/main/src/test/java/com/framsticks/gui/console/DirectConsoleTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/console/DirectConsoleTest.java	(revision 97)
+++ java/main/src/test/java/com/framsticks/gui/console/DirectConsoleTest.java	(revision 97)
@@ -0,0 +1,41 @@
+package com.framsticks.gui.console;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.communication.Address;
+import com.framsticks.communication.ClientSideRawConnection;
+import com.framsticks.gui.GuiTest;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableCollection;
+
+@Test
+public class DirectConsoleTest extends GuiTest {
+
+	ClientSideRawConnection connection;
+	DirectConsole console;
+	JoinableCollection<Joinable> joinables;
+
+	@Override
+	protected Joinable createSubject() {
+
+		connection = new ClientSideRawConnection();
+		connection.setAddress(new Address("localhost:9009"));
+
+		console = new DirectConsole().setConnection(connection);
+		joinables = new JoinableCollection<>();
+		joinables.setObservableName("connection and console");
+		joinables.add(console);
+		joinables.add(connection);
+
+		return joinables;
+	}
+
+	@Test
+	public void testCommunication() {
+		Dispatching.sleep(2.0);
+		// final Waiter waiter = produceWaiter(1.0);
+
+	}
+
+}
Index: java/main/src/test/java/com/framsticks/gui/console/TrackConsoleTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/console/TrackConsoleTest.java	(revision 97)
+++ java/main/src/test/java/com/framsticks/gui/console/TrackConsoleTest.java	(revision 97)
@@ -0,0 +1,61 @@
+package com.framsticks.gui.console;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.communication.Address;
+import com.framsticks.communication.ClientSideManagedConnection;
+import com.framsticks.communication.Connection;
+import com.framsticks.core.Path;
+import com.framsticks.gui.GuiTest;
+import com.framsticks.remote.RemoteTree;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Dispatching.Waiter;
+import com.framsticks.util.dispatching.FutureHandler;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableCollection;
+
+import static com.framsticks.core.TreeOperations.*;
+
+@Test
+public class TrackConsoleTest extends GuiTest {
+
+	RemoteTree tree;
+	TrackConsole console;
+	JoinableCollection<Joinable> joinables;
+
+	@Override
+	protected Joinable createSubject() {
+		tree = new RemoteTree();
+
+		tree.setConnection(Connection.to(new ClientSideManagedConnection(), new Address("localhost:9009")));
+
+		console = new TrackConsole().setConnection(tree.getConnection());
+		joinables = new JoinableCollection<>();
+		joinables.setObservableName("tree and console");
+		joinables.add(tree);
+		joinables.add(console);
+
+		return joinables;
+	}
+
+	@Test
+	public void testCommunication() {
+		// Dispatching.sleep(2.0);
+		final Waiter waiter = produceWaiter(1.0);
+
+		resolveAndGet(tree, "/simulator/genepools/groups/0", new FutureHandler<Path>(failOnException) {
+
+			@Override
+			protected void result(Path result) {
+				waiter.pass();
+
+			}
+		});
+		Dispatching.sleep(2.0);
+	}
+
+	@Test(dependsOnMethods = "testCommunication")
+	public void justWait() {
+		Dispatching.sleep(2.0);
+	}
+}
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 97)
@@ -4,23 +4,23 @@
 import org.testng.annotations.Test;
 
-import com.framsticks.core.ObjectInstance;
+import com.framsticks.core.Mode;
+import com.framsticks.core.ObjectTree;
 import com.framsticks.core.Path;
 import com.framsticks.core.XmlBasedTest;
-import com.framsticks.remote.RemoteInstance;
+import com.framsticks.remote.RemoteTree;
 
 import com.framsticks.test.TestClass;
-import com.framsticks.core.Instance;
+import com.framsticks.core.Tree;
 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.PrimitiveParam;
 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.FutureHandler;
 import com.framsticks.util.dispatching.RunAt;
 
-import static com.framsticks.core.InstanceUtils.*;
+import static com.framsticks.core.TreeOperations.*;
 
 import static org.fest.assertions.Assertions.*;
@@ -29,10 +29,10 @@
 public class ServerTest extends XmlBasedTest {
 
-	protected RemoteInstance remote;
+	protected RemoteTree remote;
 	protected FramsClass remoteTestFramsClass;
 	protected Path remotePath;
 
 	protected Server server;
-	protected ObjectInstance hosted;
+	protected ObjectTree hosted;
 	protected TestClass hostedObject;
 
@@ -46,10 +46,10 @@
 		assertThat(framsticks.size()).isEqualTo(2);
 		assertThat(framsticks.get("test")).isInstanceOf(Server.class);
-		assertThat(framsticks.get("remote")).isInstanceOf(RemoteInstance.class);
+		assertThat(framsticks.get("remote")).isInstanceOf(RemoteTree.class);
 
 		server = (Server) framsticks.get("test");
-		remote = (RemoteInstance) framsticks.get("remote");
-		assertThat(server.getHosted()).isInstanceOf(ObjectInstance.class);
-		hosted = (ObjectInstance) server.getHosted();
+		remote = (RemoteTree) framsticks.get("remote");
+		assertThat(server.getHosted()).isInstanceOf(ObjectTree.class);
+		hosted = (ObjectTree) server.getHosted();
 		assertThat(hosted.getRootObject()).isInstanceOf(TestClass.class);
 		hostedObject = hosted.getRootObject(TestClass.class);
@@ -58,8 +58,8 @@
 	@Test(dependsOnMethods = "runServer")
 	public void fetchInfo() {
-		remote.dispatch(new RunAt<Instance>() {
+		remote.dispatch(new RunAt<Tree>(failOnException) {
 			@Override
-			public void run() {
-				remote.fetchInfo(Path.to(remote, "/"), new Future<FramsClass>(failOnException()) {
+			protected void runAt() {
+				remote.info(Path.to(remote, "/"), new FutureHandler<FramsClass>(failOnException) {
 					@Override
 					protected void result(FramsClass result) {
@@ -78,18 +78,18 @@
 		final Waiter waiter = produceWaiter(1.0);
 
-		remote.dispatch(new RunAt<Instance>() {
+		remote.dispatch(new RunAt<Tree>(failOnException) {
 			@Override
-			public void run() {
+			protected void runAt() {
 				final Path path = Path.to(remote, "/");
 				assertThat(path.isResolved()).isFalse();
 
-				remote.resolve(path, new Future<Path>(failOnException()) {
+				remote.resolve(path, new FutureHandler<Path>(failOnException) {
 					@Override
 					protected void result(final Path result) {
 						assertThat(result.isResolved()).isTrue();
 						remotePath = result;
-						remote.fetchValues(result, new AbstractStateFunctor(failOnException()) {
+						remote.get(result, Mode.FETCH, new FutureHandler<Object>(failOnException) {
 							@Override
-							public void call() {
+							protected void result(Object object) {
 								AccessInterface access = bindAccess(result);
 								assertThat(access).isInstanceOf(PropertiesAccess.class);
@@ -108,11 +108,12 @@
 		final Waiter waiter = produceWaiter(2.0);
 
-		storeValue(remotePath, remoteTestFramsClass.getParamEntry("name", ValueParam.class), "new name", new AbstractStateFunctor(failOnException()) {
+		set(remotePath, remoteTestFramsClass.getParamEntry("name", PrimitiveParam.class), "new name", new FutureHandler<Integer>(failOnException) {
 			@Override
-			public void call() {
+			protected void result(Integer flags) {
+				// assertThat(flags).isEqualTo(0);
 				/** And now check directly whether it was really set. */
-				hosted.dispatch(new RunAt<Instance>() {
+				hosted.dispatch(new RunAt<Tree>(failOnException) {
 					@Override
-					public void run() {
+					protected void runAt() {
 						assertThat(hostedObject.getName()).isEqualTo("new name");
 						waiter.pass();
@@ -128,5 +129,5 @@
 		final Waiter waiter = produceWaiter(2.0);
 
-		call(remotePath, remoteTestFramsClass.getParamEntry("resetHistory", ProcedureParam.class), new Object[] {}, new Future<Object>(failOnException()) {
+		call(remotePath, remoteTestFramsClass.getParamEntry("resetHistory", ProcedureParam.class), new Object[] {}, new FutureHandler<Object>(failOnException) {
 			@Override
 			protected void result(Object result) {
@@ -135,10 +136,10 @@
 		});
 
-		call(remotePath, remoteTestFramsClass.getParamEntry("appendHistory", ProcedureParam.class), new Object[] {"next word"}, new Future<Object>(failOnException()) {
+		call(remotePath, remoteTestFramsClass.getParamEntry("appendHistory", ProcedureParam.class), new Object[] {"next word"}, new FutureHandler<Object>(failOnException) {
 			@Override
 			protected void result(Object result) {
-				hosted.dispatch(new RunAt<Instance>() {
+				hosted.dispatch(new RunAt<Tree>(failOnException) {
 					@Override
-					public void run() {
+					protected void runAt() {
 						assertThat(hostedObject.getHistory()).isEqualTo("next word|");
 						waiter.pass();
Index: java/main/src/test/java/com/framsticks/model/f0/SchemaTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/model/f0/SchemaTest.java	(revision 96)
+++ java/main/src/test/java/com/framsticks/model/f0/SchemaTest.java	(revision 97)
@@ -20,4 +20,6 @@
 		assertThat(schema.getNeuroClasses().size()).isEqualTo(21);
 
+		assertThat(schema.getFramsClass("m").getName()).isEqualTo("Model");
+
 		assertThat(schema.getNeuroClass("|").getName()).isEqualTo("Bend muscle");
 		assertThat(schema.getNeuroClass("VEye").getParam("p")).isInstanceOf(FloatParam.class);
Index: java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 96)
+++ java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 97)
@@ -82,10 +82,10 @@
 		access.select(test);
 
-		assertThat(access.get("history", String.class)).isEqualTo("first|");
+		assertThat(access.get("history", String.class)).isEqualTo("initial|first|");
 		Object result = access.call("appendHistory", new Object[] {"second"});
 
 		assertThat(result).isInstanceOf(Integer.class);
-		assertThat(result).isEqualTo(13);
-		assertThat(access.get("history", String.class)).isEqualTo("first|second|");
+		assertThat(result).isEqualTo(21);
+		assertThat(access.get("history", String.class)).isEqualTo("initial|first|second|");
 
 		result = access.call("resetHistory", null);
Index: java/main/src/test/java/com/framsticks/test/TestConfiguration.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 96)
+++ java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 97)
@@ -88,12 +88,9 @@
 	}
 
-	public static ExceptionResultHandler failOnException() {
-		return new ExceptionResultHandler() {
-			@Override
-			public void handle(FramsticksException e) {
-				assertThat(e).isNull();
-			}
-		};
-
-	}
+	public static final ExceptionResultHandler failOnException = new ExceptionResultHandler() {
+		@Override
+		public void handle(FramsticksException e) {
+			assertThat(e).isNull();
+		}
+	};
 }
Index: java/main/src/test/java/com/framsticks/util/lang/StringsTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/util/lang/StringsTest.java	(revision 97)
+++ java/main/src/test/java/com/framsticks/util/lang/StringsTest.java	(revision 97)
@@ -0,0 +1,20 @@
+package com.framsticks.util.lang;
+
+
+import org.testng.annotations.Test;
+
+import com.framsticks.test.TestConfiguration;
+import static org.fest.assertions.Assertions.*;
+
+@Test
+public class StringsTest extends TestConfiguration {
+
+	@Test
+	public void testStrings() {
+		assertThat(Strings.splitIntoPair("test 2", ' ', null)).isEqualTo(Pair.make("test", "2"));
+		assertThat(Strings.splitIntoPair("tes", ' ', "other")).isEqualTo(Pair.make("tes", "other"));
+		assertThat(Strings.splitIntoPair("xx yy zz", ' ', null)).isEqualTo(Pair.make("xx", "yy zz"));
+		assertThat(Strings.splitIntoPair(" empty", ' ', null)).isEqualTo(Pair.make("", "empty"));
+	}
+
+}
Index: java/main/src/test/resources/configs/FramsServerTest.xml
===================================================================
--- java/main/src/test/resources/configs/FramsServerTest.xml	(revision 96)
+++ java/main/src/test/resources/configs/FramsServerTest.xml	(revision 97)
@@ -2,9 +2,9 @@
 <Framsticks>
 	<import class="com.framsticks.running.FramsServer" />
-	<import class="com.framsticks.remote.RemoteInstance" />
+	<import class="com.framsticks.remote.RemoteTree" />
 	<import class="com.framsticks.running.LoggingOutputListener" />
 	<FramsServer name="frams" port="9008">
 		<LoggingOutputListener />
 	</FramsServer>
-	<!-- <RemoteInstance name="remote" address="localhost:9008" /> -->
+	<!-- <RemoteTree name="remote" address="localhost:9008" /> -->
 </Framsticks>
Index: java/main/src/test/resources/configs/ObjectInstanceBrowserTest.xml
===================================================================
--- java/main/src/test/resources/configs/ObjectInstanceBrowserTest.xml	(revision 96)
+++ 	(revision )
@@ -1,9 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Browser>
-	<import class="com.framsticks.model.ModelBuilder" />
-	<import class="com.framsticks.core.ObjectInstance" />
-	<import class="com.framsticks.model.ModelPackage" />
-	<ObjectInstance name="model">
-		<ModelBuilder resource="/examples/f0_example.txt" />
-	</ObjectInstance>
-</Browser>
Index: java/main/src/test/resources/configs/ObjectTreeBrowserTest.xml
===================================================================
--- java/main/src/test/resources/configs/ObjectTreeBrowserTest.xml	(revision 97)
+++ java/main/src/test/resources/configs/ObjectTreeBrowserTest.xml	(revision 97)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Browser>
+	<import class="com.framsticks.model.ModelBuilder" />
+	<import class="com.framsticks.core.ObjectTree" />
+	<import class="com.framsticks.model.ModelPackage" />
+	<ObjectTree name="model">
+		<ModelBuilder resource="/examples/f0_example.txt" />
+	</ObjectTree>
+</Browser>
Index: java/main/src/test/resources/configs/ProcedureBrowserTest.xml
===================================================================
--- java/main/src/test/resources/configs/ProcedureBrowserTest.xml	(revision 96)
+++ java/main/src/test/resources/configs/ProcedureBrowserTest.xml	(revision 97)
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Browser>
-	<import class="com.framsticks.core.ObjectInstance" />
+	<import class="com.framsticks.core.ObjectTree" />
 	<import class="com.framsticks.test.TestClass" />
-	<ObjectInstance name="test">
+	<ObjectTree name="test">
 		<TestClass />
-	</ObjectInstance>
+	</ObjectTree>
 </Browser>
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 97)
@@ -2,13 +2,13 @@
 <Framsticks>
 	<import class="com.framsticks.hosting.Server" />
-	<import class="com.framsticks.remote.RemoteInstance" />
-	<import class="com.framsticks.core.ObjectInstance" />
+	<import class="com.framsticks.remote.RemoteTree" />
+	<import class="com.framsticks.core.ObjectTree" />
 	<import class="com.framsticks.test.TestClass" />
 	<import class="com.framsticks.running.LoggingOutputListener" />
 	<Server name="server" port="9007">
-		<ObjectInstance name="test">
+		<ObjectTree name="test">
 			<TestClass name="a test name" />
-		</ObjectInstance>
+		</ObjectTree>
 	</Server>
-	<RemoteInstance name="remote" address="localhost:9007" />
+	<RemoteTree name="remote" address="localhost:9007" />
 </Framsticks>
Index: java/main/src/test/resources/configs/test.xml
===================================================================
--- java/main/src/test/resources/configs/test.xml	(revision 96)
+++ java/main/src/test/resources/configs/test.xml	(revision 97)
@@ -2,7 +2,7 @@
 <Framsticks>
 	<import class="com.framsticks.gui.Browser" />
-	<import class="com.framsticks.remote.SimulatorInstance" />
+	<import class="com.framsticks.remote.SimulatorTree" />
 	<Browser name="browser">
-		<SimulatorInstance name="localhost:9009" address="localhost:9009" />
+		<SimulatorTree name="localhost:9009" address="localhost:9009" />
 	</Browser>
 </Framsticks>
Index: java/main/src/test/resources/log4j.properties
===================================================================
--- java/main/src/test/resources/log4j.properties	(revision 96)
+++ java/main/src/test/resources/log4j.properties	(revision 97)
@@ -26,11 +26,12 @@
 log4j.appender.STDOUT.layout.ConversionPattern=%d{ABSOLUTE} [%-5p] [%t] %c -- %m%n
 
-log4j.logger.com.framsticks=INFO
-# log4j.logger.com.framsticks.hosting.Server=DEBUG
+log4j.logger.com.framsticks=WARN
+log4j.logger.com.framsticks.test.TestConfiguration=INFO
+# log4j.logger.com.framsticks.gui.console.TrackConsole=DEBUG
+# log4j.logger.com.framsticks.gui.controls.ProcedureControl=DEBUG
+# log4j.logger.com.framsticks.test.TestClass=DEBUG
 # log4j.logger.com.framsticks.communication.ServerConnection=TRACE
-# log4j.logger.com.framsticks.util.dispatching.AbstractJoinable=DEBUG
+# log4j.logger.com.framsticks.util.dispatching.Dispatching=DEBUG
 # log4j.logger.com.framsticks.parsers.F0Writer=TRACE
-# log4j.logger.com.framsticks.core.ObjectInstance=DEBUG
-# log4j.logger.com.framsticks.core.Instance=DEBUG
 # log4j.logger.com.framsticks.running=DEBUG
 # log4j.logger.com.framsticks.parsers.XmlLoader=DEBUG
