Index: java/main/src/test/java/com/framsticks/core/ListChangeTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/core/ListChangeTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/core/ListChangeTest.java	(revision 100)
@@ -1,3 +1,5 @@
 package com.framsticks.core;
+
+import java.util.Arrays;
 
 import org.testng.annotations.BeforeMethod;
@@ -6,4 +8,5 @@
 import com.framsticks.core.ListChange.Action;
 import com.framsticks.params.FramsClass;
+import com.framsticks.params.ListSink;
 import com.framsticks.params.ListSource;
 import com.framsticks.params.ReflectionAccess;
@@ -57,9 +60,13 @@
 	@Test(dependsOnMethods = "createReflectionAccess")
 	public void load() throws Exception {
-		access.select(listChange).load(ListSource.createFrom("type:2", "pos:5", "id:test"));
+		access.select(listChange).load(ListSource.createFrom("type:2", "pos:0", "id:test"));
 
 		assertThat(listChange.action).isEqualTo(Action.Modify);
-		assertThat(listChange.position).isEqualTo(5);
+		assertThat(listChange.position).isEqualTo(0);
 		assertThat(listChange.identifier).isEqualTo("test");
+
+		ListSink sink = new ListSink();
+		access.select(listChange).save(sink);
+		assertThat(sink.getOut()).isEqualTo(Arrays.asList("ListChange:", "type:2", "pos:0", "id:test", ""));
 	}
 
Index: java/main/src/test/java/com/framsticks/core/LocalTreeTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/core/LocalTreeTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/core/LocalTreeTest.java	(revision 100)
@@ -16,5 +16,5 @@
 import com.framsticks.util.dispatching.Monitor;
 import com.framsticks.util.dispatching.RunAt;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.ReflectionAccess;
 import com.framsticks.params.types.FloatParam;
@@ -72,5 +72,5 @@
 				Path path = Path.to(tree, "/");
 				assertThat(path.isResolved());
-				AccessInterface access = TreeOperations.bindAccess(path);
+				Access access = TreeOperations.bindAccess(path);
 				assertThat(access.get("se", Double.class)).isEqualTo(1.0);
 
Index: java/main/src/test/java/com/framsticks/dumping/StreamTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/dumping/StreamTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/dumping/StreamTest.java	(revision 100)
@@ -16,5 +16,5 @@
 		// 				public void result(Path result, Exception e) {
 		// 					if (e != null) {
-		// 						log.error("failed to load file: " + e);
+		// 						log.error("failed to load file: {}", e);
 		// 						fireRun(e);
 		// 						return;
@@ -26,5 +26,5 @@
 		// 			stream.load();
 		// 		} catch (IOException e) {
-		// 			log.error("io failure: " + e);
+		// 			log.error("io failure: {}", e);
 		// 			fireRun(e);
 		// 		}
Index: java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 100)
@@ -3,5 +3,6 @@
 import javax.swing.JFrame;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import org.fest.swing.edt.GuiQuery;
 import org.fest.swing.fixture.FrameFixture;
@@ -18,5 +19,5 @@
 public abstract class BrowserBaseTest extends GuiTest {
 
-	private static final Logger log = Logger.getLogger(BrowserTest.class);
+	private static final Logger log = LogManager.getLogger(BrowserTest.class);
 
 	protected Browser browser;
@@ -52,4 +53,5 @@
 		Dispatching.sleep(2.0);
 		tree.expandPath(path);
+		Dispatching.sleep(2.0);
 		robot.waitForIdle();
 	}
Index: java/main/src/test/java/com/framsticks/gui/BrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 100)
@@ -7,5 +7,6 @@
 
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import org.fest.swing.edt.GuiTask;
 import org.testng.annotations.Test;
@@ -17,5 +18,5 @@
 public class BrowserTest extends BrowserBaseTest {
 
-	private static final Logger log = Logger.getLogger(BrowserTest.class);
+	private static final Logger log = LogManager.getLogger(BrowserTest.class);
 
 	RemoteTree localhost;
@@ -34,5 +35,5 @@
 	}
 
-	@Test(timeOut = 30000)
+	@Test(timeOut = 60000)
 	public void testShow() {
 		Dispatching.synchronize(localhost, 1.0);
Index: java/main/src/test/java/com/framsticks/gui/LocalTreeBrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/LocalTreeBrowserTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/gui/LocalTreeBrowserTest.java	(revision 100)
@@ -29,5 +29,5 @@
 	}
 
-	@Test(timeOut = 10000)
+	@Test(timeOut = 30000)
 	public void testShow() {
 		tree.dispatch(new RunAt<Tree>(failOnException) {
Index: java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 100)
@@ -10,5 +10,5 @@
 import com.framsticks.core.Tree;
 import com.framsticks.core.LocalTree;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.EventListener;
 import com.framsticks.params.FramsClass;
@@ -62,8 +62,7 @@
 			@Override
 			protected void runAt() {
-				AccessInterface access = bindAccess(tree, "/");
+				Access access = bindAccess(tree, "/");
 				assertThat(access).isInstanceOf(ReflectionAccess.class);
 				FramsClass framsClass = access.getFramsClass();
-				assertThat(framsClass.getParamCount()).isEqualTo(5);
 				assertThat(framsClass.getParam(0).getId()).isEqualTo("name");
 				assertThat(framsClass.getParam(1).getId()).isEqualTo("history");
@@ -94,5 +93,5 @@
 			@Override
 			protected void runAt() {
-				AccessInterface access = bindAccess(tree, "/");
+				Access access = bindAccess(tree, "/");
 				assertThat(access.get("history", String.class)).isEqualTo("initial|Żółw|");
 
@@ -107,5 +106,5 @@
 			@Override
 			protected void runAt() {
-				AccessInterface access = bindAccess(tree, "/");
+				Access access = bindAccess(tree, "/");
 				assertThat(access.get("history", String.class)).isEqualTo("");
 
Index: java/main/src/test/java/com/framsticks/hosting/ServerTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/hosting/ServerTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/hosting/ServerTest.java	(revision 100)
@@ -8,4 +8,5 @@
 import org.testng.annotations.Test;
 
+import com.framsticks.core.ListChange;
 import com.framsticks.core.LocalTree;
 import com.framsticks.core.Path;
@@ -18,9 +19,10 @@
 import com.framsticks.core.Tree;
 import com.framsticks.params.FramsClass;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.EventListener;
 import com.framsticks.params.PrimitiveParam;
 import com.framsticks.params.PropertiesAccess;
 import com.framsticks.params.types.EventParam;
+import com.framsticks.params.types.StringParam;
 // import com.framsticks.params.types.EventParam;
 import com.framsticks.params.types.ProcedureParam;
@@ -44,5 +46,9 @@
 	protected TestClass hostedObject;
 	protected EventListener<ChangeEvent> listener;
+	protected EventListener<ListChange> childListener;
+
 	protected List<String> listenerArguments = new LinkedList<>();
+	protected List<ListChange> childrenChanges = new LinkedList<>();
+
 
 	@Override
@@ -90,5 +96,5 @@
 				assertThat(path.isResolved()).isTrue();
 				remotePath = path;
-				AccessInterface access = bindAccess(path);
+				Access access = bindAccess(path);
 				assertThat(access).isInstanceOf(PropertiesAccess.class);
 				assertThat(access.get("name", String.class)).isEqualTo("a test name");
@@ -167,5 +173,54 @@
 	}
 
-	@Test(dependsOnMethods = "callMethod")
+
+	@Test(dependsOnMethods = "deregisterListener")
+	public void registerChildListener() {
+
+		childListener = new EventListener<ListChange>() {
+			@Override
+			public void action(ListChange listChange) {
+				childrenChanges.add(listChange);
+			}
+		};
+
+		addListener(remotePath, remoteTestFramsClass.getParamEntry("children_changed", EventParam.class), childListener, ListChange.class, produceWaiter(1.0).passInFuture(Void.class));
+	}
+
+	@Test(dependsOnMethods = "registerChildListener")
+	public void createChild() {
+		final Waiter waiter = produceWaiter(2.0);
+		call(remotePath, "createChild", new Object[] { "a child" }, produceWaiter(2.0).passInFuture(Object.class));
+		call(remotePath, "createChild", new Object[] { "another child" }, produceWaiter(2.0).passInFuture(Object.class));
+
+		tryGet(remote, "/testClass/children/c0", new FutureHandler<Path>(failOnException) {
+
+			@Override
+			protected void result(Path result) {
+				set(result, getFramsClass(result).getParamEntry("name", StringParam.class), "new_name", new FutureHandler<Integer>(failOnException) {
+
+					@Override
+					protected void result(Integer result) {
+						waiter.pass();
+					}
+				});
+			}
+		});
+	}
+
+	@Test(dependsOnMethods = "createChild")
+	public void deregisterChildListener() {
+		removeListener(remotePath, remoteTestFramsClass.getParamEntry("children_changed", EventParam.class), childListener, produceWaiter(1.0).passInFuture(Void.class));
+	}
+
+	@Test(dependsOnMethods = "deregisterChildListener")
+	public void checkListChanges() {
+		assertThat(childrenChanges).isEqualTo(Arrays.asList(
+			new ListChange(ListChange.Action.Add, 0, "c0"),
+			new ListChange(ListChange.Action.Add, 1, "c1"),
+			new ListChange(ListChange.Action.Modify, 0, "c0")
+		));
+	}
+
+	@Test(dependsOnMethods = "checkListChanges")
 	public void endWait() {
 		monitor.useFor(1.0);
Index: java/main/src/test/java/com/framsticks/model/ModelPackageTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/model/ModelPackageTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/model/ModelPackageTest.java	(revision 100)
@@ -21,5 +21,4 @@
 	@Test(dataProvider = "classesList")
 	public void testFramsClass(Class<?> javaClass, String name, int paramCount, Object[][] paramsTests) throws InstantiationException, IllegalAccessException {
-		// log.info("testing " + name + " " + javaClass + " " + Package.class.getResource(filename));
 		String filename = "/info/" + name + ".info";
 		InputStream stream = ModelPackage.class.getResourceAsStream(filename);
Index: java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 100)
@@ -34,5 +34,5 @@
 	@Test
 	public void checkProcedureParams() {
-		assertThat(framsClass.getParamCount()).isEqualTo(5);
+		assertThat(framsClass.getParamCount()).isEqualTo(8);
 
 		assertThat(framsClass.getParam("name")).isInstanceOf(StringParam.class);
@@ -80,4 +80,20 @@
 					"name:ResetHistory",
 					"type:p()",
+					"",
+					"prop:",
+					"id:children",
+					"name:Children",
+					"type:l TestChild uid",
+					"flags:1",
+					"",
+					"prop:",
+					"id:createChild",
+					"name:CreateChild",
+					"type:p(s arg0)",
+					"",
+					"prop:",
+					"id:children_changed",
+					"name:ChildrenListener",
+					"type:e ListChange",
 					""
 				)
Index: java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java	(revision 100)
@@ -14,5 +14,5 @@
 	ParamBuilder builder;
 	FramsClass builderFramsClass;
-	AccessInterface access;
+	Access access;
 
 	@Test
@@ -34,5 +34,5 @@
 		MultiParamLoader loader = new MultiParamLoader();
 		loader.setNewSource(source);
-		loader.addAccessInterface(access);
+		loader.addAccess(access);
 		loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
 
Index: java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java	(revision 100)
@@ -24,5 +24,5 @@
 
 	private Schema schema;
-	private List<AccessInterface> accesses;
+	private List<Access> accesses;
 	private List<ModelComponent> components;
 	private Model model;
@@ -72,6 +72,6 @@
 
 	@Test(dependsOnMethods = {"readF0"})
-	public void stripAccessInterface() {
-		components = Util.stripAccessInterface(accesses, ModelComponent.class);
+	public void stripAccess() {
+		components = Util.stripAccess(accesses, ModelComponent.class);
 
 		assertThat(components.get(1)).isInstanceOf(Part.class);
@@ -81,5 +81,5 @@
 	}
 
-	@Test(dependsOnMethods = {"stripAccessInterface"})
+	@Test(dependsOnMethods = {"stripAccess"})
 	public void buildModel() {
 		model = new ModelBuilder().addComponents(components).finish();
Index: java/main/src/test/java/com/framsticks/test/TestConfiguration.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 100)
@@ -6,6 +6,6 @@
 import java.util.Set;
 
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import org.testng.annotations.*;
 
@@ -21,10 +21,9 @@
 public class TestConfiguration {
 
-	private static final Logger log = Logger.getLogger(TestConfiguration.class);
+	private static final Logger log = LogManager.getLogger(TestConfiguration.class);
 
 	@BeforeClass
 	public void setUpConfiguration() {
-		PropertyConfigurator.configure(TestConfiguration.class.getResource("/log4j.properties"));
-		log.info("testing " + this.getClass());
+		log.info("testing {}", this.getClass());
 	}
 
@@ -86,10 +85,14 @@
 	@BeforeMethod
 	public void clearWaiters() {
-		waiters.clear();
+		synchronized (waiters) {
+			waiters.clear();
+		}
 	}
 
 	protected Dispatching.Waiter produceWaiter(double timeOut) {
 		Waiter waiter = new Waiter(timeOut, failOnException);
-		waiters.add(waiter);
+		synchronized (waiters) {
+			waiters.add(waiter);
+		}
 		return waiter;
 	}
@@ -98,5 +101,5 @@
 		@Override
 		public void handle(FramsticksException e) {
-			log.error("passing exception as assertion in " + TestConfiguration.this.getClass(), e);
+			log.error("passing exception as assertion in {}", TestConfiguration.this.getClass(), e);
 			addAsyncAssertion(e);
 		}
Index: java/main/src/test/resources/log4j.properties
===================================================================
--- java/main/src/test/resources/log4j.properties	(revision 99)
+++ 	(revision )
@@ -1,43 +1,0 @@
-# -------------------------------------------------------------------
-# Global logger configuration
-# -------------------------------------------------------------------
-#log4j.rootLogger=INFO, STDOUT, FILE
-log4j.rootLogger=DEBUG, STDOUT
-
-
-# -------------------------------------------------------------------
-# Disable certain libraries from spamming the output
-# -------------------------------------------------------------------
-
-# Apache commons
-log4j.logger.org.apache.commons=WARN
-
-# HttpClient
-log4j.logger.httpclient=WARN
-
-# -------------------------------------------------------------------
-# Define appenders.
-# -------------------------------------------------------------------
-
-# A plain console appender
-log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
-log4j.appender.STDOUT.Target=System.out
-log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
-log4j.appender.STDOUT.layout.ConversionPattern=%d{ABSOLUTE} [%-5p] [%t] %c -- %m%n
-
-log4j.logger.com.framsticks=WARN
-log4j.logger.com.framsticks.test.TestConfiguration=INFO
-# log4j.logger.com.framsticks.hosting.Cli=DEBUG
-# log4j.logger.com.framsticks.core.AbstractTree=DEBUG
-# log4j.logger.com.framsticks.remote.RemoteTree=DEBUG
-# 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.Dispatching=DEBUG
-# log4j.logger.com.framsticks.parsers.F0Writer=TRACE
-# log4j.logger.com.framsticks.running=DEBUG
-# log4j.logger.com.framsticks.parsers.XmlLoader=DEBUG
-# log4j.logger.com.framsticks.parsers.MultiParamLoader=TRACE
-# log4j.logger.com.framsticks.gui.controls.SliderControl=TRACE
-# log4j.logger.com.framsticks.communication.ClientConnection=DEBUG
Index: java/main/src/test/resources/log4j2.xml
===================================================================
--- java/main/src/test/resources/log4j2.xml	(revision 100)
+++ java/main/src/test/resources/log4j2.xml	(revision 100)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration status="WARN">
+	<appenders>
+		<Console name="Console" target="SYSTEM_OUT">
+			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+		</Console>
+	</appenders>
+	<loggers>
+		<logger name="com.framsticks" level="warn" />
+		<logger name="com.framsticks.test.TestConfiguration" level="info" />
+		<root level="info">
+			<appender-ref ref="Console"/>
+		</root>
+	</loggers>
+</configuration>
