diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/LMHWorkflow.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/LMHWorkflow.java
index c97e6b97c474340874571f5c7fb265bed79293b2..6a589787607a3d0de3ae51d1c33d7c84f0f91235 100644
--- a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/LMHWorkflow.java
+++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/LMHWorkflow.java
@@ -1,20 +1,14 @@
 package info.kwarc.sally4.mathhubworker.impl;
 
 import info.kwarc.sally4.core.CamelContextProvider;
-import info.kwarc.sally4.core.SallyInteractionResultAcceptor;
-import info.kwarc.sally4.core.SallyService;
-import info.kwarc.sally4.core.SallyServiceProvider;
 import info.kwarc.sally4.docmanager.AlexRoute;
 import info.kwarc.sally4.docmanager.IDocWorkflow;
+import info.kwarc.sally4.docmanager.IDocWorkflowInstance;
 import info.kwarc.sally4.mathhubworker.MathHubWorkerManager;
-import info.kwarc.sally4.mathhubworker.internal.comm.GetLMHWorkers;
-import info.kwarc.sally4.mathhubworker.routes.LMHRoute;
-
-import java.util.HashMap;
-import java.util.Map;
+import info.kwarc.sally4.mathhubworker.routes.LMHWorkflowInstance;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.Exchange;
+import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.felix.ipojo.annotations.Component;
 import org.apache.felix.ipojo.annotations.Instantiate;
 import org.apache.felix.ipojo.annotations.Provides;
@@ -22,37 +16,20 @@ import org.apache.felix.ipojo.annotations.Requires;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 @Component
 @Instantiate
 @Provides
-public class LMHWorkflow extends WorkflowCommon implements IDocWorkflow, SallyServiceProvider {
+public class LMHWorkflow implements IDocWorkflow {
 	@Requires
 	CamelContextProvider camelContextProvider;
 
 	@Requires
 	MathHubWorkerManager workerManager;
-
-	Map<String, CamelContext> routeContexts;
-	Map<String, String> routeWorkerIDs;
 	
 	Logger log;
 
 	public LMHWorkflow() {
 		log = LoggerFactory.getLogger(getClass());
-		routeContexts = new HashMap<String, CamelContext>();
-		routeWorkerIDs = new HashMap<String, String>();
-	}
-
-	public void setWorkerKey(String AlexRouteID, String workerID) {
-		routeWorkerIDs.put(AlexRouteID, workerID);
-	}
-	
-	@SallyService
-	public void getLMHWorkers(GetLMHWorkers click, SallyInteractionResultAcceptor acceptor, Exchange context) {
-		for (String s : routeWorkerIDs.values()) {
-			acceptor.acceptResult(s);
-		}
 	}
 	
 	@Override
@@ -66,42 +43,16 @@ public class LMHWorkflow extends WorkflowCommon implements IDocWorkflow, SallySe
 	}
 
 	@Override
-	public boolean handleMessage(AlexRoute route, String namespace, String type,
-			Exchange exchange) {
-		
-		return false;
-	}
-
-	@Override
-	public void startRoutes(CamelContext camelContext, final AlexRoute route) {
-		workerManager.addNewWorker(route);
+	public IDocWorkflowInstance createDocumentInstance(AlexRoute route) {
+		CamelContext context = new DefaultCamelContext();
+		LMHWorkflowInstance lmhWorkflowInstance = new LMHWorkflowInstance(route);
 		try {
-			camelContext.addRoutes(new LMHRoute(route, this));
-			camelContext.addComponent("mhw", route.getAlexComponent());
-			camelContext.start();
-			camelContext.createProducerTemplate().sendBody("direct:start", "");
-			
-			route.addOnStopHandler(new Runnable() {
-				
-				@Override
-				public void run() {
-					routeWorkerIDs.remove(route.getID());
-				}
-			});
+			context.addRoutes(lmhWorkflowInstance);
+			context.start();
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
-		
-	}
-
-	@Override
-	public String[] getContextComponentsToCopy() {
-		return new String[]{"activemq"};
-	}
-	
-	@Override
-	public CamelContextProvider getCamelContextProvider() {
-		return camelContextProvider;
+		return lmhWorkflowInstance;
 	}
 
 }
diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubEnvironment.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubEnvironment.java
index a362f62564f0cb204aa87134b990853da7c515b0..08ecec31465e3bce71a0da6f4168fc5d0efd786b 100644
--- a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubEnvironment.java
+++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubEnvironment.java
@@ -18,12 +18,12 @@ public class MathHubEnvironment {
 	}
 	
 	public void addWorker(final AlexRoute worker) {
-		workers.put(worker.getID(), worker);
+		workers.put(worker.getDocQueue(), worker);
 		worker.addOnStopHandler(new Runnable() {
 			
 			@Override
 			public void run() {
-				workers.remove(worker.getID());
+				workers.remove(worker.getDocQueue());
 				if (workers.size() == 0 && onEmpty != null) {
 					onEmpty.run();
 				}
diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/PlanetaryClientWorkflow.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/PlanetaryClientWorkflow.java
index 82ebce787e221a117ae5f86272d5de4a6b802605..1cda804e2a376dceffc3f2c4cc167c35e40ab7d0 100644
--- a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/PlanetaryClientWorkflow.java
+++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/PlanetaryClientWorkflow.java
@@ -1,27 +1,16 @@
 package info.kwarc.sally4.mathhubworker.impl;
 
-import info.kwarc.sally.comm.planetaryclient.NewService;
 import info.kwarc.sally4.core.CamelContextProvider;
 import info.kwarc.sally4.core.SallyInteraction;
 import info.kwarc.sally4.docmanager.AlexRoute;
 import info.kwarc.sally4.docmanager.IDocWorkflow;
-import info.kwarc.sally4.marshalling.MarshallUtils;
-import info.kwarc.sally4.mathhubworker.internal.comm.GetLMHWorkers;
-import info.kwarc.sally4.mathhubworker.routes.PlanetaryClientRoute;
+import info.kwarc.sally4.docmanager.IDocWorkflowInstance;
+import info.kwarc.sally4.mathhubworker.routes.PlanetaryClientWorkflowInstance;
 import info.kwarc.sally4.planetary.PlanetaryConnection;
 import info.kwarc.sally4.servlet.SallyServlet;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-
-import javax.xml.ws.RequestWrapper;
-
 import org.apache.camel.CamelContext;
-import org.apache.camel.Exchange;
-import org.apache.camel.Property;
-import org.apache.camel.RecipientList;
+import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.felix.ipojo.annotations.Component;
 import org.apache.felix.ipojo.annotations.Instantiate;
 import org.apache.felix.ipojo.annotations.Invalidate;
@@ -32,7 +21,7 @@ import org.apache.felix.ipojo.annotations.Validate;
 @Component
 @Instantiate
 @Provides
-public class PlanetaryClientWorkflow extends WorkflowCommon implements IDocWorkflow {
+public class PlanetaryClientWorkflow implements IDocWorkflow {
 	String planetaryClientNamespace = "http://kwarc.info/sally/comm/planetaryclient";
 	
 	@Requires
@@ -53,27 +42,8 @@ public class PlanetaryClientWorkflow extends WorkflowCommon implements IDocWorkf
 	
 	@Invalidate
 	public void stop() {
-	
-	}
-
-	@Override
-	public String[] getContextComponentsToCopy() {
-		return new String[] {"activemq", "planetary"};
 	}
 	
-	public void startRoutes(CamelContext camelContext, AlexRoute route) {		
-		camelContext.addComponent("alex", route.getAlexComponent());
-		
-		try {
-			camelContext.start();
-			camelContext.addRoutes(new PlanetaryClientRoute(this));
-			camelContext.createProducerTemplate().sendBody("direct:start", route);
-		} catch (Exception e) {
-			log.error(e.getMessage());
-			e.printStackTrace();
-		}
-	}
-
 	public String[] getInterfaceRequirements() {
 		return new String[]{"planetaryclient"};
 	}
@@ -81,60 +51,23 @@ public class PlanetaryClientWorkflow extends WorkflowCommon implements IDocWorkf
 	public String[] getHandlingNamespaces() {
 		return new String[] { planetaryClientNamespace };
 	}
-	
-	public List<String> getFreeAvailableKeys(Exchange e) {
-		@SuppressWarnings("unchecked")
-		List<HashMap<String, String>> takenKeys = (List<HashMap<String, String>>) e.getIn().getBody(List.class);
-		HashSet<String> taken = new HashSet<String>();
-		for (HashMap<String, String> takenKey : takenKeys) {
-			taken.add(takenKey.get("key"));
-		}
-		List<String> result = new ArrayList<String>();
-		List<String> availableKeys = interact.getPossibleInteractions(new GetLMHWorkers(), String.class, e);
-		for (String aKey : availableKeys) {
-			if (taken.contains(result))
-				continue;
-			availableKeys.add(aKey);
-		}
-		return result;
-	}
 
-	// very simple 
-	public String getNewMHW(List<String> availableKeys, @Property("uid") Long uid) {
-		if (availableKeys.size()==0)
-			return null;
-		return availableKeys.get(0);
-	}
-	
-	public void addService(AlexRoute route, NewService serviceDesk) {
+	@Override
+	public IDocWorkflowInstance createDocumentInstance(AlexRoute route) {
+		CamelContext context = new DefaultCamelContext();
 		
-	}
-	
-	public boolean handleMessage(AlexRoute route, String namespace, String type, Exchange exchange) {
-		CamelContext context = this.routeContexts.get(route.getID());
-		if (context == null) // should not really happen
-			return false;
-
-		log.info("responding to "+type);
-		if (type.equals("GetServices")) {
-			NewService serv = new NewService();
-			String host = "http://localhost:8181/sally";
-			serv.setIcon(host+"/planetary/libs/mhwsettings.png");
-			serv.setId("mhwsettings");
-			serv.setName("Math Hub Worker Settings");
-			serv.setType("toolbar");
-			serv.setUrl(host+"/planetary/mhwsettings?id="+route.getID());
-			String xml = MarshallUtils.marshallToXML("planetaryclient", serv, getClass().getClassLoader());
-			log.info("sending back"+xml);
-			exchange.getIn().setBody(xml);
-			return true;
+		PlanetaryClientWorkflowInstance planetaryWorkflowInstance = new PlanetaryClientWorkflowInstance(
+				camelContextProvider.getComponent("activemq"), 
+				route.getAlexComponent(),
+				camelContextProvider.getComponent("planetary"),
+				interact);
+		
+		try {
+			context.addRoutes(planetaryWorkflowInstance);
+			context.start();
+		} catch (Exception e) {
+			e.printStackTrace();
 		}
-		return false;
+		return planetaryWorkflowInstance;
 	}
-
-	@Override
-	public CamelContextProvider getCamelContextProvider() {
-		return camelContextProvider;
-	}
-	
 }
diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/WorkflowCommon.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/WorkflowCommon.java
deleted file mode 100644
index c72ef61407d6c24c37b35d43cf4c56698817d361..0000000000000000000000000000000000000000
--- a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/WorkflowCommon.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package info.kwarc.sally4.mathhubworker.impl;
-
-import info.kwarc.sally4.core.CamelContextProvider;
-import info.kwarc.sally4.docmanager.AlexRoute;
-import info.kwarc.sally4.docmanager.IDocWorkflow;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.impl.DefaultCamelContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class WorkflowCommon implements IDocWorkflow {
-	Map<String, CamelContext> routeContexts;
-	Logger log;
-	
-	
-	public WorkflowCommon() {
-		log = LoggerFactory.getLogger(getClass());
-		routeContexts = new HashMap<String, CamelContext>();
-	}
-	
-	public abstract void startRoutes(CamelContext camelContext, AlexRoute route);
-	public abstract String [] getContextComponentsToCopy();
-	public abstract CamelContextProvider getCamelContextProvider();
-
-	public void onNewDocument(final AlexRoute route) {
-		CamelContext camelContext = new DefaultCamelContext();
-		camelContext.getShutdownStrategy().setTimeout(1);
-		CamelContextProvider camelGlobalProvider = getCamelContextProvider();
-		
-		for (String comp : getContextComponentsToCopy()) {
-			camelContext.addComponent(comp, camelGlobalProvider.getComponent(comp));
-		}
-		
-		routeContexts.put(route.getID(), camelContext);
-		
-		route.addOnStopHandler(new Runnable() {
-			
-			public void run() {
-				try {
-					if (routeContexts.containsKey(route.getID())) {
-						routeContexts.get(route.getID()).stop();						
-					}
-				} catch (Exception e) {
-					e.printStackTrace();
-				} finally {
-					routeContexts.remove(route);
-				}
-			}
-		});
-		
-		startRoutes(camelContext, route);
-		
-		
-	}
-}
diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/LMHRoute.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/LMHWorkflowInstance.java
similarity index 65%
rename from MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/LMHRoute.java
rename to MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/LMHWorkflowInstance.java
index cde74a9dc2d17ba207711cb7b991b1b9f1fc2eb9..b2df397069eee8bbf42660ca2b81bfedfc3e09ac 100644
--- a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/LMHRoute.java
+++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/LMHWorkflowInstance.java
@@ -3,32 +3,32 @@ package info.kwarc.sally4.mathhubworker.routes;
 import info.kwarc.sally.comm.mathhubworker.GetAuthKeyRequest;
 import info.kwarc.sally.comm.mathhubworker.GetAuthKeyResponse;
 import info.kwarc.sally4.docmanager.AlexRoute;
+import info.kwarc.sally4.docmanager.IDocWorkflowInstance;
 import info.kwarc.sally4.marshalling.CommUtils;
-import info.kwarc.sally4.mathhubworker.impl.LMHWorkflow;
 
+import org.apache.camel.Exchange;
 import org.apache.camel.ExchangeTimedOutException;
 import org.apache.camel.LoggingLevel;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.spi.DataFormat;
 
-public class LMHRoute extends RouteBuilder {
+public class LMHWorkflowInstance extends RouteBuilder implements IDocWorkflowInstance {
 
-	AlexRoute thisRoute;
-	LMHWorkflow thisWorklow;
+	AlexRoute route;
 	
-	public LMHRoute(AlexRoute thisRoute, LMHWorkflow thisWorkflow) {		
-		this.thisRoute = thisRoute;
-		this.thisWorklow = thisWorkflow;
+	public LMHWorkflowInstance(AlexRoute route) {		
+		this.route = route;
 	}
 	
 	public void setWorkerKey(GetAuthKeyResponse response) {
-		thisWorklow.setWorkerKey(thisRoute.getID(), response.getAuthkey());
+//		thisWorklow.setWorkerKey(route.getID(), response.getAuthkey());
 	}
 	
 	
 	@Override
 	public void configure() throws Exception {
 		DataFormat worker = CommUtils.getDataFormat("mathhubworker", getClass().getClassLoader());
+		getContext().addComponent("alex", route.getAlexComponent());
 		
 		from("direct:start")
 			.to("direct:requestAuthKey");
@@ -47,4 +47,16 @@ public class LMHRoute extends RouteBuilder {
 			.bean(method(this, "setWorkerKey"));
 	}
 
+	@Override
+	public boolean handleMessage(AlexRoute route, String namespace,
+			String type, Exchange exchange) {
+		return false;
+	}
+
+	@Override
+	public void stop() {
+		// TODO Auto-generated method stub
+		
+	}
+
 }
diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/PlanetaryClientRoute.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/PlanetaryClientRoute.java
deleted file mode 100644
index 38f73f6306d78be5ba26b08d8dda7a8c4b0df5c5..0000000000000000000000000000000000000000
--- a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/PlanetaryClientRoute.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package info.kwarc.sally4.mathhubworker.routes;
-
-import info.kwarc.sally.comm.planetaryclient.GetSessionIDRequest;
-import info.kwarc.sally.comm.planetaryclient.GetSessionIDResponse;
-import info.kwarc.sally4.marshalling.CommUtils;
-import info.kwarc.sally4.mathhubworker.impl.PlanetaryClientWorkflow;
-import info.kwarc.sally4.processors.FileServeProcessor;
-
-import org.apache.camel.ExchangeTimedOutException;
-import org.apache.camel.LoggingLevel;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spi.DataFormat;
-
-public class PlanetaryClientRoute extends RouteBuilder {
-
-	PlanetaryClientWorkflow thisWorkflow;
-	
-	public PlanetaryClientRoute(PlanetaryClientWorkflow thisWorkflow) {
-		this.thisWorkflow = thisWorkflow;
-	}
-	
-	public String getSessionID(GetSessionIDResponse response) {
-		return response.getSessionid();
-	}
-	
-	@Override
-	public void configure() throws Exception {
-		DataFormat planetaryClient = CommUtils.getDataFormat("planetaryclient", getClass().getClassLoader());
-		
-		from("direct:start")
-			.to("direct:requestSessionID")
-			.to("direct:getPlanetaryUser")
-			.to("direct:assignMHW");
-			
-		
-		from("direct:requestSessionID")
-			.setBody(constant(new GetSessionIDRequest()))
-			.marshal(planetaryClient)
-				.doTry()
-					.inOut("alex:requestSession")
-				.doCatch(ExchangeTimedOutException.class)
-					.log(LoggingLevel.ERROR,"MathHubRoute","Alex did not respond to GetSessionIDRequest. Ending this route.")
-					.stop()
-				.doFinally()
-			.unmarshal(planetaryClient)
-			.bean(method(this, "getSessionID"))
-			.setProperty("sessionid", body());
-		
-		
-		from("direct:getPlanetaryUser")
-			.setBody(property("sessionid"))
-			.inOut("planetary:select uid from sessions where sid=#?outputType=SelectOne")
-			.setProperty("uid", body())
-				.choice()
-					.when(simple("${body} == null"))
-						.log(LoggingLevel.ERROR,"MathHubRoute","SessionID could not be found in planetary database.")
-						.stop()
-				.endChoice();
-		
-		from("direct:assignMHW")
-			.inOut("planetary:select 'key' from mhw_assignment where uid=#?outputType=SelectOne")
-			.choice()
-				.when(simple("${body} == null"))
-//					.to("direct:getNewMHW")
-				.endChoice();
-	
-		/*
-		from("direct:getNewMHW")
-		// get already taken keys
-			.inOut("planetary:select 'key' from mhw_assignment")
-		// compute list of free and available keys
-			.bean(thisWorkflow, "getFreeAvailableKeys")
-		// choose one key based on user info
-			.bean(thisWorkflow, "getNewMHW")
-			.choice()
-			.when(simple("${body} == null"))
-				.end()
-			.endChoice()
-		*/
-	}
-
-}
diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/PlanetaryClientWorkflowInstance.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/PlanetaryClientWorkflowInstance.java
new file mode 100644
index 0000000000000000000000000000000000000000..f17dbc93c94355ed5ec58b4e7245707237528f75
--- /dev/null
+++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/PlanetaryClientWorkflowInstance.java
@@ -0,0 +1,152 @@
+package info.kwarc.sally4.mathhubworker.routes;
+
+import info.kwarc.sally.comm.planetaryclient.GetSessionIDRequest;
+import info.kwarc.sally.comm.planetaryclient.GetSessionIDResponse;
+import info.kwarc.sally.comm.planetaryclient.NewService;
+import info.kwarc.sally4.core.SallyInteraction;
+import info.kwarc.sally4.docmanager.AlexRoute;
+import info.kwarc.sally4.docmanager.IDocWorkflowInstance;
+import info.kwarc.sally4.marshalling.CommUtils;
+import info.kwarc.sally4.marshalling.MarshallUtils;
+import info.kwarc.sally4.mathhubworker.internal.comm.GetLMHWorkers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.camel.Component;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangeTimedOutException;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.Property;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.DataFormat;
+
+public class PlanetaryClientWorkflowInstance extends RouteBuilder implements IDocWorkflowInstance {
+
+	SallyInteraction interact;
+	Component activemqComponent;
+	Component alexComponent;
+	Component planetaryComponent;
+	
+	public PlanetaryClientWorkflowInstance(Component activemqComponent, Component alexComponent, Component planetaryComponent, SallyInteraction interact) {
+		this.interact = interact;
+		this.activemqComponent = activemqComponent;
+		this.alexComponent = alexComponent;
+		this.planetaryComponent = planetaryComponent;
+	}
+
+	public String getSessionID(GetSessionIDResponse response) {
+		return response.getSessionid();
+	}
+
+	public List<String> getFreeAvailableKeys(Exchange e) {
+		@SuppressWarnings("unchecked")
+		List<HashMap<String, String>> takenKeys = (List<HashMap<String, String>>) e.getIn().getBody(List.class);
+		HashSet<String> taken = new HashSet<String>();
+		for (HashMap<String, String> takenKey : takenKeys) {
+			taken.add(takenKey.get("key"));
+		}
+		List<String> result = new ArrayList<String>();
+		List<String> availableKeys = interact.getPossibleInteractions(new GetLMHWorkers(), String.class, e);
+		for (String aKey : availableKeys) {
+			if (taken.contains(result))
+				continue;
+			availableKeys.add(aKey);
+		}
+		return result;
+	}
+
+	// very simple 
+	public String getNewMHW(List<String> availableKeys, @Property("uid") Long uid) {
+		if (availableKeys.size()==0)
+			return null;
+		return availableKeys.get(0);
+	}
+	
+	@Override
+	public void configure() throws Exception {
+		DataFormat planetaryClient = CommUtils.getDataFormat("planetaryclient", getClass().getClassLoader());
+		getContext().addComponent("activemq", activemqComponent);
+		getContext().addComponent("alex", alexComponent);
+		getContext().addComponent("planetary", planetaryComponent);
+
+		from("direct:start")
+		.to("direct:requestSessionID")
+		.to("direct:getPlanetaryUser")
+		.to("direct:assignMHW");
+
+
+		from("direct:requestSessionID")
+		.setBody(constant(new GetSessionIDRequest()))
+		.marshal(planetaryClient)
+		.doTry()
+		.inOut("alex:requestSession")
+		.doCatch(ExchangeTimedOutException.class)
+		.log(LoggingLevel.ERROR,"MathHubRoute","Alex did not respond to GetSessionIDRequest. Ending this route.")
+		.stop()
+		.doFinally()
+		.unmarshal(planetaryClient)
+		.bean(method(this, "getSessionID"))
+		.setProperty("sessionid", body());
+
+
+		from("direct:getPlanetaryUser")
+		.setBody(property("sessionid"))
+		.inOut("planetary:select uid from sessions where sid=#?outputType=SelectOne")
+		.setProperty("uid", body())
+		.choice()
+		.when(simple("${body} == null"))
+		.log(LoggingLevel.ERROR,"MathHubRoute","SessionID could not be found in planetary database.")
+		.stop()
+		.endChoice();
+
+		from("direct:assignMHW")
+		.inOut("planetary:select 'key' from mhw_assignment where uid=#?outputType=SelectOne")
+		.choice()
+		.when(simple("${body} == null"))
+		//					.to("direct:getNewMHW")
+		.endChoice();
+
+		/*
+		from("direct:getNewMHW")
+		// get already taken keys
+			.inOut("planetary:select 'key' from mhw_assignment")
+		// compute list of free and available keys
+			.bean(thisWorkflow, "getFreeAvailableKeys")
+		// choose one key based on user info
+			.bean(thisWorkflow, "getNewMHW")
+			.choice()
+			.when(simple("${body} == null"))
+				.end()
+			.endChoice()
+		 */
+	}
+
+	@Override
+	public boolean handleMessage(AlexRoute route, String namespace,
+			String type, Exchange exchange) {
+
+		if (type.equals("GetServices")) {
+			NewService serv = new NewService();
+			String host = "http://localhost:8181/sally";
+			serv.setIcon(host+"/planetary/libs/mhwsettings.png");
+			serv.setId("mhwsettings");
+			serv.setName("Math Hub Worker Settings");
+			serv.setType("toolbar");
+			serv.setUrl(host+"/planetary/mhwsettings?id="+route.getDocQueue());
+			String xml = MarshallUtils.marshallToXML("planetaryclient", serv, getClass().getClassLoader());
+			log.info("sending back"+xml);
+			exchange.getIn().setBody(xml);
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public void stop() {
+
+	}
+
+}
diff --git a/docmanager/pom.xml b/docmanager/pom.xml
index c9303c21a576834f3143d3dd4538de4bd8f4ea18..44e46ce9a9e997ea9f4e8a2833174e57d95833ac 100644
--- a/docmanager/pom.xml
+++ b/docmanager/pom.xml
@@ -42,13 +42,19 @@
 			<artifactId>activemq</artifactId>
 			<version>${sally4.version}</version>
 		</dependency>
-		
+
 		<dependency>
 			<groupId>info.kwarc.sally4</groupId>
 			<artifactId>utils</artifactId>
 			<version>${sally4.version}</version>
 		</dependency>
 
+		<dependency>
+			<groupId>info.kwarc.sally4</groupId>
+			<artifactId>servlet</artifactId>
+			<version>${sally4.version}</version>
+		</dependency>
+
 		<dependency>
 			<groupId>org.apache.felix</groupId>
 			<artifactId>org.apache.felix.ipojo.annotations</artifactId>
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/AlexRoute.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/AlexRoute.java
index b41d18c2521459f18cfafc3178ce50fa89649d54..5ba51ffdef4697f6cd70538a016041dbeb12b975 100644
--- a/docmanager/src/main/java/info/kwarc/sally4/docmanager/AlexRoute.java
+++ b/docmanager/src/main/java/info/kwarc/sally4/docmanager/AlexRoute.java
@@ -1,15 +1,17 @@
 package info.kwarc.sally4.docmanager;
 
 import info.kwarc.sally4.components.ProducerConsumerSplitterComponent;
+import info.kwarc.sally4.processors.TypedCallback;
+import info.kwarc.sally4.processors.XMLMessageWithTypeInfo;
 
 
 public interface AlexRoute {
-	public String getID();
-	public String getAlexStateQueue();
-	public String getAlexQueue();
+	public String getDocStateQueue();
+	public String getDocQueue();
 	public String getEnvironmentID();
 	public String getUserID();
 	public ProducerConsumerSplitterComponent getAlexComponent();
 	
 	public void addOnStopHandler(Runnable r);
+	public void setMessageHandler(TypedCallback<XMLMessageWithTypeInfo> callback);
 }
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/IDocWorkflow.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/IDocWorkflow.java
index 009763aef063b4ae363f0866b3a38d7f030cc099..df32659eb70670ff15b4ba8b5a724e256e5ab009 100644
--- a/docmanager/src/main/java/info/kwarc/sally4/docmanager/IDocWorkflow.java
+++ b/docmanager/src/main/java/info/kwarc/sally4/docmanager/IDocWorkflow.java
@@ -1,11 +1,9 @@
 package info.kwarc.sally4.docmanager;
 
-import org.apache.camel.Exchange;
 
 public interface IDocWorkflow {
 	String [] getInterfaceRequirements();
 	String [] getHandlingNamespaces();
 	
-	boolean handleMessage(AlexRoute route, String namespace, String type, Exchange exchange);
-	void onNewDocument(AlexRoute route);
+	IDocWorkflowInstance createDocumentInstance(AlexRoute route);
 }
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/IDocWorkflowInstance.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/IDocWorkflowInstance.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b1afefc8db3f025b9d009fc04503c0f6bf78877
--- /dev/null
+++ b/docmanager/src/main/java/info/kwarc/sally4/docmanager/IDocWorkflowInstance.java
@@ -0,0 +1,9 @@
+package info.kwarc.sally4.docmanager;
+
+import org.apache.camel.Exchange;
+
+public interface IDocWorkflowInstance {
+	boolean handleMessage(AlexRoute route, String namespace, String type, Exchange exchange);
+	
+	void stop();
+}
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/TestMain.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/TestMain.java
index 4563d6a20c83d75bc1523268a351d44ada5a27af..44b99418e0609c75a478af9f719bb7982d02a2f0 100644
--- a/docmanager/src/main/java/info/kwarc/sally4/docmanager/TestMain.java
+++ b/docmanager/src/main/java/info/kwarc/sally4/docmanager/TestMain.java
@@ -4,7 +4,6 @@ import info.kwarc.sally.comm.core.Heartbeatrequest;
 import info.kwarc.sally.comm.core.Heartbeatresponse;
 import info.kwarc.sally.comm.core.Registerdocument;
 import info.kwarc.sally.comm.core.Registerdocumentresponse;
-import info.kwarc.sally4.docmanager.routes.SallyRegisterRoute;
 import info.kwarc.sally4.marshalling.CommUtils;
 import info.kwarc.sally4.predicates.BodyHasType;
 
@@ -61,7 +60,7 @@ public class TestMain extends RouteBuilder {
 		from("direct:client-register")
 			.marshal(core)
 			.to("log:too")
-				.inOut("activemq:queue:"+SallyRegisterRoute.sallyRegisterQueue)
+				//.inOut("activemq:queue:"+SallyRegisterRoute.sallyRegisterQueue)
 			.unmarshal(core)
 			.process(new Processor() {
 				public void process(Exchange exchange) throws Exception {
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/AlexRouteImpl.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/AlexRouteImpl.java
index 51bac57e6aa13cf5044a07e026e2f206f1b7679e..1ff0d42636ef7c4ae40624bb9c67a84ffed4203e 100644
--- a/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/AlexRouteImpl.java
+++ b/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/AlexRouteImpl.java
@@ -1,41 +1,37 @@
 package info.kwarc.sally4.docmanager.impl;
 
+import info.kwarc.sally.comm.core.Heartbeatrequest;
 import info.kwarc.sally4.components.ProducerConsumerSplitterComponent;
 import info.kwarc.sally4.docmanager.AlexRoute;
-import info.kwarc.sally4.docmanager.IDocWorkflow;
+import info.kwarc.sally4.marshalling.CommUtils;
 import info.kwarc.sally4.processors.EnrichMessageProperties;
+import info.kwarc.sally4.processors.TypedCallback;
+import info.kwarc.sally4.processors.XMLMessageWithTypeInfo;
 
-import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Queue;
-import java.util.UUID;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.Header;
+import org.apache.camel.ExchangeTimedOutException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.DataFormat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
-public class AlexRouteImpl implements AlexRoute {
+public class AlexRouteImpl extends RouteBuilder  implements AlexRoute {
 
-	String alexQueue;
+	String docQueue;
 	String environmentid;
 	String userid;
 	
-	HashSet<String> interfaces;
+	String docStateQueue;
+
+	String[] interfaces;
 	List<Runnable> stopHandlers;
-	
-	Queue<IDocWorkflow> workflows;
-	String ID;
-	
+	TypedCallback<XMLMessageWithTypeInfo> messageHandler;
 	Logger log;
 	
-	String alexStateQueue;
-
 	String generateUUID(String doc_queue) {
 		//"/queue/sally_doc_"+UUID.randomUUID().toString()
 		return "sally_doc_"+doc_queue;
@@ -49,62 +45,38 @@ public class AlexRouteImpl implements AlexRoute {
 		return userid;
 	}
 	
-	public void forwardMessage(Exchange e, 
-			@Header(EnrichMessageProperties.MessageNamespace) String namespace, 
-			@Header(EnrichMessageProperties.MessageType) String msgType) {
-
-		Iterator<IDocWorkflow> iter = workflows.iterator();
-		while (iter.hasNext()) {
-			IDocWorkflow work = iter.next();
-			for (String s : work.getHandlingNamespaces()) {
-				if (s.equals(namespace)) {
-					if (work.handleMessage(this, namespace, msgType, e)) {
-						return;
-					}
-				}
-			}
-		}
-	}
-	
-	public AlexRouteImpl(String alexQueue, String environmentid, String userid, Collection<String> interfaces) {
+	public AlexRouteImpl(String alexQueue, String environmentid, String userid, String[] interfaces) {
 		log = LoggerFactory.getLogger(getClass());
-		this.alexQueue = alexQueue;
+		this.docQueue = alexQueue;
 		this.environmentid = environmentid;
 		this.userid = userid;
 		
-		this.interfaces = new HashSet<String>(interfaces);
-		this.alexStateQueue = generateUUID(alexQueue);
+		this.interfaces = interfaces;
+		this.docStateQueue = generateUUID(alexQueue);
 		stopHandlers = new ArrayList<Runnable>();
-		workflows = new ArrayDeque<IDocWorkflow>();
-		ID = UUID.randomUUID().toString();
 	}	
 	
-	public void addDocumentWorkflow(IDocWorkflow workflow) {
-		workflows.add(workflow);
-		workflow.onNewDocument(this);
-	}
-
-	public void removeDocumentWorkflow(IDocWorkflow workflow) {
-		workflows.remove(workflow);
+	public Heartbeatrequest generateHeartbeat() {
+		return new Heartbeatrequest();
 	}
 	
-	public String getAlexStateQueue() {
-		return alexStateQueue;
+	public String getDocStateQueue() {
+		return docStateQueue;
 	}
 	
-	public String getAlexQueue() {
-		return alexQueue;
+	public String getDocQueue() {
+		return docQueue;
 	}
 
 	public void addOnStopHandler(Runnable stopHandler) {
 		stopHandlers.add(stopHandler);
 	}
 
-	public HashSet<String> getInterfaces() {
+	public String[] getInterfaces() {
 		return interfaces;
 	}
 	
-	public void stop() {
+	public void notifyStop() {
 		for (Runnable r : stopHandlers) {
 			try {
 				r.run();
@@ -112,27 +84,67 @@ public class AlexRouteImpl implements AlexRoute {
 				e.printStackTrace();
 			}
 		}
-	}
-
-	@Override
-	public String getID() {
-		return ID;
+		try {
+			getContext().stopRoute("timer");
+			getContext().stop();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
 	}
 
 	@Override
 	public ProducerConsumerSplitterComponent getAlexComponent() {
-		return new ProducerConsumerSplitterComponent("activemq:queue:"+alexStateQueue, "activemq:queue:"+alexQueue);
+		return new ProducerConsumerSplitterComponent("activemq:queue:"+docStateQueue, "activemq:queue:"+docQueue);
 	}
 
 	@Override
 	public String getEnvironmentID() {
-		// TODO Auto-generated method stub
-		return null;
+		return environmentid;
 	}
 
 	@Override
 	public String getUserID() {
-		// TODO Auto-generated method stub
-		return null;
+		return userid;
+	}
+		
+	@Override
+	public void configure() throws Exception {
+		DataFormat core = CommUtils.getDataFormat("core", getClass().getClassLoader());
+
+		/**
+		 * Sends a Heartbeat message to the Alex. if it does not respond after 20sec, this route will shutdown.
+		 */
+		from("timer://foo?fixedRate=true&period=60000")
+			.id("timer")
+			.bean(method(this, "generateHeartbeat"))
+			.marshal(core)
+			.doTry()				
+				.inOut("alex:default")
+			.doCatch(ExchangeTimedOutException.class)
+				.bean(method(this, "notifyStop"))
+				.stop();
+				
+		/**
+		 * 
+		 */
+		from("alex:defaultin")
+			.convertBodyTo(String.class)
+			.process(new EnrichMessageProperties())
+			.bean(method(this, "triggerOnMessageHandlers"))
+			.to("log:willsend");
+	}
+
+	@Override
+	public void setMessageHandler(TypedCallback<XMLMessageWithTypeInfo> callback) {
+		messageHandler = callback;
+	}
+	
+	public String triggerOnMessageHandlers(Exchange exchange) {
+		XMLMessageWithTypeInfo info = exchange.getIn().getBody(XMLMessageWithTypeInfo.class);
+		info.setExchange(exchange);
+		if (messageHandler != null) {
+			messageHandler.run(info);
+		}
+		return exchange.getIn().getBody(String.class);
 	}
 }
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerAdapter.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..d75eec45835807e04094a68daa1daad8ba48969b
--- /dev/null
+++ b/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerAdapter.java
@@ -0,0 +1,153 @@
+package info.kwarc.sally4.docmanager.impl;
+
+import info.kwarc.sally.comm.core.Registerdocument;
+import info.kwarc.sally.comm.core.Registerdocumentresponse;
+import info.kwarc.sally4.activemq.ActiveMQService;
+import info.kwarc.sally4.components.TemplatingComponent;
+import info.kwarc.sally4.core.CamelContextProvider;
+import info.kwarc.sally4.docmanager.AlexRoute;
+import info.kwarc.sally4.docmanager.DocumentManager;
+import info.kwarc.sally4.docmanager.IDocWorkflow;
+import info.kwarc.sally4.marshalling.CommUtils;
+import info.kwarc.sally4.servlet.SallyServlet;
+
+import java.util.HashMap;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.DataFormat;
+import org.apache.felix.ipojo.annotations.Bind;
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Instantiate;
+import org.apache.felix.ipojo.annotations.Invalidate;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.annotations.Requires;
+import org.apache.felix.ipojo.annotations.Unbind;
+import org.apache.felix.ipojo.annotations.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is the adapter class that manages all documents handled by Sally. 
+ * @author Constantin Jucovschi
+ *
+ */
+@Component
+@Instantiate
+@Provides
+public class DocumentManagerAdapter extends RouteBuilder implements DocumentManager  {
+	public static final String sallyRegisterQueue = "sally_register";
+
+	@Requires(optional=true)
+	IDocWorkflow[] workflows;
+	
+	@Requires 	SallyServlet servlet;
+	@Requires 	ActiveMQService activeMQ;
+
+	DocumentManagerModel model;
+
+	@Requires
+	CamelContextProvider camelContextProvider;
+
+	CamelContext camelContext;
+	Logger log;
+
+	public HashMap<String, Object> prepareDocManagement() {
+		HashMap<String, Object> result = new HashMap<String, Object>();
+		result.put("routes", model.getRoutes());
+		return result;
+	}
+
+	public Registerdocumentresponse createRouteContext(AlexRouteImpl route) throws Exception {
+		final CamelContext alexRouteContext = new DefaultCamelContext();
+		alexRouteContext.addComponent("activemq", camelContextProvider.getComponent("activemq"));
+		alexRouteContext.addComponent("alex", route.getAlexComponent());
+
+		alexRouteContext.addRoutes(route);
+		alexRouteContext.getShutdownStrategy().setTimeout(10);
+		alexRouteContext.start();
+
+		/*
+		route.addOnStopHandler(new Runnable() {
+
+			public void run() {
+				try {
+					alexRouteContext.stop();
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		});
+		*/
+		
+		Registerdocumentresponse response = new Registerdocumentresponse();
+		response.setSallyqueue(route.getDocStateQueue());
+		return response;
+	}
+
+	@Override
+	public void configure() throws Exception {
+		DataFormat core = CommUtils.getDataFormat("core", getClass().getClassLoader());
+
+		getContext().addComponent("freemarker", new TemplatingComponent("templates/", getClass().getClassLoader()));
+
+		from("sallyservlet:///docmanager")
+		.bean(method(this, "prepareDocManagement"))
+		.to("freemarker:test.html");
+
+		from("activemq:queue:"+sallyRegisterQueue)
+		.unmarshal(core)
+		.bean(method(this, "registerDocument"))			
+		.setProperty("route", body())
+		.bean(method(this, "createRouteContext"))
+		.marshal(core);
+	}
+
+	public DocumentManagerAdapter() {
+		log = LoggerFactory.getLogger(getClass());	
+		model  = new DocumentManagerModel();
+	}
+
+	@Bind(aggregate=true, optional=true)
+	private void bindWorkflow(IDocWorkflow workflow) 
+	{
+		model.addWorkflow(workflow);
+	}
+
+	@Unbind(aggregate=true, optional=true)
+	private void unbindWorkflow(IDocWorkflow workflow) 
+	{ 
+		model.removeWorkflow(workflow);
+	}
+
+
+	@Validate
+	public void start() throws Exception{
+		camelContext = new DefaultCamelContext();
+		camelContext.addComponent("activemq", camelContextProvider.getComponent("activemq"));
+		camelContext.addComponent("sallyservlet", camelContextProvider.getComponent("sallyservlet"));
+		camelContext.addRoutes(this);
+		camelContext.start();
+	}
+
+	@Invalidate
+	public void stop() throws Exception {
+		camelContext.stop();
+		model.stopAllRoutes();
+	}
+
+	@Override
+	public AlexRoute registerDocument(Registerdocument doc) {
+		final AlexRoute route =  model.addDocument(doc.getDocumentqueue(), doc.getDocumentqueue(), doc.getUserid(), doc.getInterfaces().toArray(new String[0]));
+		route.addOnStopHandler(new Runnable() {
+
+			@Override
+			public void run() {
+				model.removeDocument(route.getDocQueue());
+			}
+		});
+		return route;
+	}
+
+}
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerImpl.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerImpl.java
deleted file mode 100644
index 90edf9894c00e452426661ac5534e9b8f9c5f41d..0000000000000000000000000000000000000000
--- a/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerImpl.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package info.kwarc.sally4.docmanager.impl;
-
-import info.kwarc.sally.comm.core.Registerdocument;
-import info.kwarc.sally4.activemq.ActiveMQService;
-import info.kwarc.sally4.core.CamelContextProvider;
-import info.kwarc.sally4.docmanager.AlexRoute;
-import info.kwarc.sally4.docmanager.DocumentManager;
-import info.kwarc.sally4.docmanager.IDocWorkflow;
-import info.kwarc.sally4.docmanager.routes.DocumentManagementRoute;
-import info.kwarc.sally4.docmanager.routes.SallyRegisterRoute;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.impl.DefaultCamelContext;
-import org.apache.felix.ipojo.annotations.Bind;
-import org.apache.felix.ipojo.annotations.Component;
-import org.apache.felix.ipojo.annotations.Instantiate;
-import org.apache.felix.ipojo.annotations.Invalidate;
-import org.apache.felix.ipojo.annotations.Provides;
-import org.apache.felix.ipojo.annotations.Requires;
-import org.apache.felix.ipojo.annotations.Unbind;
-import org.apache.felix.ipojo.annotations.Validate;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Component
-@Instantiate
-@Provides
-public class DocumentManagerImpl implements DocumentManager {
-
-	@Requires(optional=true)
-	IDocWorkflow[] workflows;
-
-	@Requires
-	ActiveMQService activeMQ;
-
-	@Requires
-	CamelContextProvider camelContextProvider;
-	
-	Map<String, AlexRouteImpl> docs;
-	SallyRegisterRoute registerRoute;
-
-	CamelContext camelContext;
-
-	Logger log;
-
-
-	public DocumentManagerImpl() {
-		docs = new HashMap<String, AlexRouteImpl>();
-		registerRoute = new SallyRegisterRoute(this);
-		log = LoggerFactory.getLogger(getClass());		
-	}
-
-	public AlexRoute registerDocument(Registerdocument doc) {
-		if (docs.containsKey(doc.getDocumentqueue()))
-			return docs.get(doc.getDocumentqueue());
-
-		final AlexRouteImpl route = new AlexRouteImpl(doc.getDocumentqueue(), doc.getEnvironmentid(), doc.getUserid(), doc.getInterfaces());
-		route.addOnStopHandler(new Runnable() {
-			
-			@Override
-			public void run() {
-				docs.remove(route.getAlexQueue());
-			}
-		});
-		docs.put(doc.getDocumentqueue(), route);
-				
-		return route;
-	}
-	
-	public void addRouteToWorkflows(AlexRouteImpl route) {
-		for (IDocWorkflow workflow : workflows) {
-			HashSet<String> required = new HashSet<String>(Arrays.asList(workflow.getInterfaceRequirements()));
-			if (route.getInterfaces().containsAll(required)) {
-				route.addDocumentWorkflow(workflow);
-			}
-		}
-	}
-	
-	public HashMap<String, Object> prepareDocManagement() {
-		HashMap<String, Object> result = new HashMap<String, Object>();
-		result.put("routes", docs.values());
-		return result;
-	}
-
-
-	@Bind(aggregate=true, optional=true)
-	private void bindWorkflow(IDocWorkflow workflow) 
-	{ 
-		HashSet<String> required = new HashSet<String>(Arrays.asList(workflow.getInterfaceRequirements()));
-		for (AlexRouteImpl route : docs.values()) {
-			if (route.getInterfaces().containsAll(required)) {
-				route.addDocumentWorkflow(workflow);
-			}
-		}
-	}
-
-	@Unbind(aggregate=true, optional=true)
-	private void unbindWorkflow(IDocWorkflow workflow) 
-	{ 
-		for (AlexRouteImpl route : docs.values()) {
-			route.removeDocumentWorkflow(workflow);
-		}
-	}
-
-
-	@Validate
-	public void start() {
-		try {
-			camelContext = new DefaultCamelContext();
-			camelContext.addComponent("activemq", camelContextProvider.getComponent("activemq"));
-			camelContext.addComponent("sallyservlet", camelContextProvider.getComponent("sallyservlet"));
-			camelContext.addRoutes(registerRoute);
-			camelContext.addRoutes(new DocumentManagementRoute(this));
-			camelContext.start();
-		} catch (Exception e) {
-			log.info(e.getMessage());
-			e.printStackTrace();
-		}
-
-	}
-
-	@Invalidate
-	public void stop() {
-		try {
-			camelContext.stop();
-			for (AlexRouteImpl route : docs.values()) {
-				route.stop();
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-}
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerModel.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ef58c469a38a9f91bc6792f380e635f20f690ae
--- /dev/null
+++ b/docmanager/src/main/java/info/kwarc/sally4/docmanager/impl/DocumentManagerModel.java
@@ -0,0 +1,134 @@
+package info.kwarc.sally4.docmanager.impl;
+
+import info.kwarc.sally4.docmanager.AlexRoute;
+import info.kwarc.sally4.docmanager.IDocWorkflow;
+import info.kwarc.sally4.docmanager.IDocWorkflowInstance;
+import info.kwarc.sally4.processors.TypedCallback;
+import info.kwarc.sally4.processors.XMLMessageWithTypeInfo;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class DocumentManagerModel {
+	Map<String, AlexRouteImpl> documents;
+	HashSet<IDocWorkflow> workflows;
+
+	HashMap<String, HashMap<IDocWorkflow, IDocWorkflowInstance>> workflowDocInstances;
+
+	public DocumentManagerModel() {
+		documents = new HashMap<String, AlexRouteImpl>();
+		workflows = new HashSet<IDocWorkflow>();
+
+		workflowDocInstances = new HashMap<String, HashMap<IDocWorkflow,IDocWorkflowInstance>>();
+	}
+	
+	// N^2 algo but the strings list are small so will be faster
+	public boolean containsAll(String[] required, String[]  available) {
+		boolean ok;
+		for (String req : required) {
+			ok = false;
+			for (String avail : available) {
+				if (req.equals(avail)) {
+					ok = true;
+					break;
+				}
+			}
+   			if (!ok)
+				return false;
+		}
+		return true;
+	}
+	
+	public AlexRoute addDocument(String docQueue, String environment, String userid, String[] interfaces) {
+		if (documents.containsKey(docQueue))
+			return documents.get(docQueue);
+
+		final AlexRouteImpl route = new AlexRouteImpl(docQueue, environment, userid, interfaces);
+		documents.put(docQueue, route);
+		route.setMessageHandler(new TypedCallback<XMLMessageWithTypeInfo>() {
+			
+			@Override
+			public void run(XMLMessageWithTypeInfo obj) {
+				forwardMessage(route, obj);
+			}
+		});
+		
+		HashMap<IDocWorkflow,IDocWorkflowInstance> workflowInstances = new HashMap<IDocWorkflow, IDocWorkflowInstance>();
+		for (IDocWorkflow workflow : workflows) {
+			if (containsAll(workflow.getInterfaceRequirements(), interfaces)) {
+				IDocWorkflowInstance instance = workflow.createDocumentInstance(route);
+				workflowInstances.put(workflow, instance);
+			}
+		}
+		workflowDocInstances.put(docQueue, workflowInstances);
+		return route;
+	}
+	
+	public void removeDocument(String docQueue) {
+		if (!documents.containsKey(docQueue))
+			return;
+		documents.remove(docQueue);
+		for (IDocWorkflowInstance instances : workflowDocInstances.get(docQueue).values()) {
+			instances.stop();
+		}
+		workflowDocInstances.remove(docQueue);
+	}
+	
+	public void addWorkflow(IDocWorkflow workflow) {
+		workflows.add(workflow);
+		
+		for (AlexRouteImpl route : getRoutes()) {
+			if (containsAll(workflow.getInterfaceRequirements(), route.getInterfaces())) {
+				workflowDocInstances.get(route.getDocQueue()).put(workflow,  workflow.createDocumentInstance(route));
+			}
+		}
+	}
+	
+	public void removeWorkflow(IDocWorkflow workflow) {
+		workflows.remove(workflow);
+		for (AlexRouteImpl route : getRoutes()) {
+			 final HashMap<IDocWorkflow, IDocWorkflowInstance> instanceMap = workflowDocInstances.get(route.getDocQueue());
+			 
+			 IDocWorkflowInstance t = instanceMap.get(workflow);
+			 if (t == null)
+				 continue;
+			 t.stop();
+			 instanceMap.remove(workflow);
+		}
+	}	
+
+	
+	public void forwardMessage(AlexRoute r, XMLMessageWithTypeInfo info) {
+		final HashMap<IDocWorkflow, IDocWorkflowInstance> workflows = workflowDocInstances.get(r.getDocQueue());
+		for (Entry<IDocWorkflow, IDocWorkflowInstance> work : workflows.entrySet()) {
+			if (containsAll(new String[] {info.getXmlMessageNamespace()}, work.getKey().getHandlingNamespaces())) {
+				if (work.getValue().handleMessage(r, info.getXmlMessageNamespace(), info.getXmlMessageType(), info.getExchange())) {
+					return;
+				}
+			}
+		}
+	}
+		
+	public Collection<AlexRouteImpl> getRoutes() {
+		return documents.values();
+	}
+	
+	public void stopAllRoutes() {
+		for (String routeID : workflowDocInstances.keySet()) {
+			for (IDocWorkflow workflow : workflowDocInstances.get(routeID).keySet()) {
+				workflowDocInstances.get(routeID).get(workflow).stop();
+			}
+			try {
+				documents.get(routeID).getContext().stop();
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+			workflowDocInstances.get(routeID).clear();
+		}
+		workflowDocInstances.clear();
+		documents.clear();
+	}
+}
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/DocumentManagementRoute.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/DocumentManagementRoute.java
deleted file mode 100644
index fd00dff93795d59e12b175ca558873f8955ec104..0000000000000000000000000000000000000000
--- a/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/DocumentManagementRoute.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package info.kwarc.sally4.docmanager.routes;
-
-import info.kwarc.sally4.components.TemplatingComponent;
-import info.kwarc.sally4.docmanager.impl.DocumentManagerImpl;
-
-import org.apache.camel.builder.RouteBuilder;
-
-public class DocumentManagementRoute extends RouteBuilder {
-	DocumentManagerImpl manager;
-	
-	public DocumentManagementRoute(DocumentManagerImpl manager) {
-		this.manager = manager;
-	}
-	
-	@Override
-	public void configure() throws Exception {
-		getContext().addComponent("freemarker", new TemplatingComponent("templates/", getClass().getClassLoader()));
-
-		from("sallyservlet:///docmanager")
-			.bean(method(manager, "prepareDocManagement"))
-			.to("freemarker:test.html");
-	}
-
-}
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/SallyAlexRoute.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/SallyAlexRoute.java
deleted file mode 100644
index b7251f4676e26f476e293c565daca4024b5edac9..0000000000000000000000000000000000000000
--- a/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/SallyAlexRoute.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package info.kwarc.sally4.docmanager.routes;
-
-import info.kwarc.sally.comm.core.Heartbeatrequest;
-import info.kwarc.sally4.docmanager.impl.AlexRouteImpl;
-import info.kwarc.sally4.docmanager.impl.DocumentManagerImpl;
-import info.kwarc.sally4.marshalling.CommUtils;
-import info.kwarc.sally4.processors.EnrichMessageProperties;
-
-import org.apache.camel.ExchangeTimedOutException;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spi.DataFormat;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SallyAlexRoute extends RouteBuilder  {
-
-	Logger log;
-	AlexRouteImpl thisAlexRoute;
-	DocumentManagerImpl docManager;
-	
-	public Heartbeatrequest generateHeartbeat() {
-		return new Heartbeatrequest();
-	}
-	
-	public void stopSallyRoute() {
-		thisAlexRoute.stop();
-	}
-	
-	SallyAlexRoute(AlexRouteImpl thisAlexRoute) {
-		log = LoggerFactory.getLogger(getClass());
-		this.thisAlexRoute = thisAlexRoute;
-	}
-	
-	@Override
-	public void configure() throws Exception {
-		DataFormat core = CommUtils.getDataFormat("core", getClass().getClassLoader());
-
-		/**
-		 * Sends a Heartbeat message to the Alex. if it does not respond after 20sec, this route will shutdown.
-		 */
-		from("timer://foo?fixedRate=true&period=60000")
-			.bean(method(this, "generateHeartbeat"))
-			.marshal(core)
-			.doTry()				
-				.inOut("alex:default")
-			.doCatch(ExchangeTimedOutException.class)
-				.bean(method(this, "stopSallyRoute"));
-				
-		/**
-		 * 
-		 */
-		from("alex:defaultin")
-			.convertBodyTo(String.class)
-			.process(new EnrichMessageProperties())
-			.bean(thisAlexRoute, "forwardMessage");
-			//.to("alex:defaultout");		
-	}
-	
-	
-
-}
diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/SallyRegisterRoute.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/SallyRegisterRoute.java
deleted file mode 100644
index 446b9a4fa71f8313969331ad09344ba4e39d3e9b..0000000000000000000000000000000000000000
--- a/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/SallyRegisterRoute.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package info.kwarc.sally4.docmanager.routes;
-
-import info.kwarc.sally.comm.core.Registerdocumentresponse;
-import info.kwarc.sally4.docmanager.impl.AlexRouteImpl;
-import info.kwarc.sally4.docmanager.impl.DocumentManagerImpl;
-import info.kwarc.sally4.marshalling.CommUtils;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.jms.JmsConstants;
-import org.apache.camel.impl.DefaultCamelContext;
-import org.apache.camel.spi.DataFormat;
-
-public class SallyRegisterRoute extends RouteBuilder {
-
-	public static final String sallyRegisterQueue = "sally_register";
-	public static final String directSallyRegisterQueue = "direct:/queue/sally_register";
-	public static final String mockSallyRegisterQueueOutput = "mock:/queue/sally_register_out";
-
-	DocumentManagerImpl docManager;
-
-	public SallyRegisterRoute(DocumentManagerImpl docManager) {
-		this.docManager = docManager;
-	}
-
-	public Registerdocumentresponse createRouteContext(AlexRouteImpl route) throws Exception {
-		final CamelContext alexRouteContext = new DefaultCamelContext();
-		alexRouteContext.addComponent("activemq", getContext().getComponent("activemq"));
-		alexRouteContext.addComponent("alex", route.getAlexComponent());
-		
-		alexRouteContext.addRoutes(new SallyAlexRoute(route));
-		alexRouteContext.getShutdownStrategy().setTimeout(10);
-		alexRouteContext.start();
-
-		route.addOnStopHandler(new Runnable() {
-
-			public void run() {
-				try {
-					alexRouteContext.stop();
-				} catch (Exception e) {
-					e.printStackTrace();
-				}
-			}
-		});
-		Registerdocumentresponse response = new Registerdocumentresponse();
-		response.setSallyqueue(route.getAlexStateQueue());
-		return response;
-	}
-
-	@Override
-	public void configure() throws Exception {
-		DataFormat core = CommUtils.getDataFormat("core", getClass().getClassLoader());
-		
-		from("activemq:queue:"+sallyRegisterQueue)
-			.unmarshal(core)
-			.bean(docManager, "registerDocument")			
-			.setProperty("route", body())
-			.bean(method(this, "createRouteContext"))
-			.setExchangePattern(ExchangePattern.InOnly)
-			.multicast().parallelProcessing()
-				.to("direct:sendResponse", "direct:alexRoute");
-				
-		from("direct:alexRoute")
-			.setBody(property("route"))
-			.bean(docManager, "addRouteToWorkflows")
-			.end();
-
-		from("direct:sendResponse")
-			.marshal(core)
-			.setHeader(JmsConstants.JMS_DESTINATION, header("JMSReplyTo"))
-			.to("activemq:mock");
-	}
-
-}
diff --git a/docmanager/src/test/java/info/kwarc/sally4/docmanager/impl/DocumentManagerAdapterTest.java b/docmanager/src/test/java/info/kwarc/sally4/docmanager/impl/DocumentManagerAdapterTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..51752f1a1b4ba41036de243393ca82760abd42d4
--- /dev/null
+++ b/docmanager/src/test/java/info/kwarc/sally4/docmanager/impl/DocumentManagerAdapterTest.java
@@ -0,0 +1,40 @@
+package info.kwarc.sally4.docmanager.impl;
+
+import info.kwarc.sally.comm.core.Registerdocument;
+import info.kwarc.sally4.docmanager.mocks.MockGlobalContextProvider;
+import info.kwarc.sally4.marshalling.MarshallUtils;
+
+import org.apache.camel.ProducerTemplate;
+import org.junit.Test;
+
+public class DocumentManagerAdapterTest {
+
+	Registerdocument r1;
+	String r1xml;
+	
+	public DocumentManagerAdapterTest() {
+		r1 = new Registerdocument();
+		r1.setDocumentqueue("d1");
+		r1.setEnvironmentid("e1");
+		r1xml = MarshallUtils.marshallToXML("core", r1, getClass().getClassLoader());
+	}
+	
+	@Test
+	public void testStartingAndStopping() throws Exception {
+		DocumentManagerAdapter adapter = new DocumentManagerAdapter();
+		adapter.camelContextProvider = new MockGlobalContextProvider();
+		adapter.start();
+		adapter.stop();
+	}
+
+	@Test
+	public void testRegisteringNewDocument() throws Exception {
+		DocumentManagerAdapter adapter = new DocumentManagerAdapter();
+		adapter.camelContextProvider = new MockGlobalContextProvider();
+		adapter.start();
+		ProducerTemplate temp = adapter.camelContext.createProducerTemplate();
+		temp.sendBody("activemq:queue:"+DocumentManagerAdapter.sallyRegisterQueue, r1);
+		adapter.stop();
+	}
+
+}
diff --git a/docmanager/src/test/java/info/kwarc/sally4/docmanager/impl/DocumentManagerModelTest.java b/docmanager/src/test/java/info/kwarc/sally4/docmanager/impl/DocumentManagerModelTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a96b5367665890666db421cf4b7e84e5d246b691
--- /dev/null
+++ b/docmanager/src/test/java/info/kwarc/sally4/docmanager/impl/DocumentManagerModelTest.java
@@ -0,0 +1,165 @@
+package info.kwarc.sally4.docmanager.impl;
+
+import static org.junit.Assert.*;
+import info.kwarc.sally4.docmanager.AlexRoute;
+import info.kwarc.sally4.docmanager.mocks.MockCountingWorkflow;
+
+import org.junit.Test;
+
+public class DocumentManagerModelTest {
+
+	DocumentManagerModel model;
+
+	public DocumentManagerModelTest() {
+		model = new DocumentManagerModel();
+	}
+
+	@Test
+	public void testSameQueueSameRoute() {
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2"});
+		AlexRoute route2 = model.addDocument("doc1", "env2", "user2", new String[] {"i1", "i2"});
+
+		assertEquals("env1", route2.getEnvironmentID());
+		assertEquals("user1", route2.getUserID());
+	}
+
+	@Test
+	public void testRemovingRoute() {
+		AlexRoute route1 = model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2"});
+		model.removeDocument(route1.getDocQueue());
+
+		AlexRoute route2 = model.addDocument("doc1", "env2", "user2", new String[] {"i1", "i2"});
+		assertEquals("env2", route2.getEnvironmentID());
+		assertEquals("user2", route2.getUserID());
+	}
+
+	@Test
+	public void testRemovingAllRoutes() {
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2"});
+		model.addDocument("doc2", "env1", "user1", new String[] {"i1", "i2"});
+		model.addDocument("doc3", "env1", "user1", new String[] {"i1", "i2"});
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2"});
+		model.removeDocument("doc1");
+		model.removeDocument("doc2");
+		model.removeDocument("doc3");
+		assertEquals(0, model.getRoutes().size());
+	}
+
+	@Test
+	public void testMatchingRouteAndWorkflow() {
+		MockCountingWorkflow cnt1 = new MockCountingWorkflow(new String[]{"i1"}, new String[]{"n1"});
+		MockCountingWorkflow cnt2 = new MockCountingWorkflow(new String[]{"i1", "i3"}, new String[]{"n1"});
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2", "i3"});
+		model.addDocument("doc2", "env2", "user2", new String[] {"i1", "i2"});
+		model.addWorkflow(cnt1);
+		assertEquals(2, cnt1.getInstances());
+		model.addWorkflow(cnt2);
+		assertEquals(1, cnt2.getInstances());
+	}	
+
+	@Test
+	public void testMatchingRouteAndWorkflowAndRemovingRoute() {
+		MockCountingWorkflow cnt1 = new MockCountingWorkflow(new String[]{"i1"}, new String[]{"n1"});
+		MockCountingWorkflow cnt2 = new MockCountingWorkflow(new String[]{"i1", "i3"}, new String[]{"n1"});
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2", "i3"});
+		model.addDocument("doc2", "env2", "user2", new String[] {"i1", "i2"});
+		model.addWorkflow(cnt1);
+		assertEquals(2, cnt1.getInstances());
+		model.addWorkflow(cnt2);
+		assertEquals(1, cnt2.getInstances());
+		model.removeDocument("doc1");
+
+		assertEquals(1, cnt1.getInstances());
+		assertEquals(0, cnt2.getInstances());
+	}	
+
+	@Test
+	public void testMatchingRouteAndWorkflowAndRemovingWorkflow() {
+		MockCountingWorkflow cnt1 = new MockCountingWorkflow(new String[]{"i1"}, new String[]{"n1"});
+		MockCountingWorkflow cnt2 = new MockCountingWorkflow(new String[]{"i1", "i3"}, new String[]{"n1"});
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2", "i3"});
+		model.addDocument("doc2", "env2", "user2", new String[] {"i1", "i2"});
+		model.addWorkflow(cnt1);
+		assertEquals(2, cnt1.getInstances());
+		model.addWorkflow(cnt2);
+		assertEquals(1, cnt2.getInstances());
+		model.removeWorkflow(cnt1);
+
+		assertEquals(0, cnt1.getInstances());
+		assertEquals(1, cnt2.getInstances());
+	}	
+
+	@Test
+	public void testMatchingRouteAndWorkflowAndRemovingAllWorkflows() {
+		MockCountingWorkflow cnt1 = new MockCountingWorkflow(new String[]{"i1"}, new String[]{"n1"});
+		MockCountingWorkflow cnt2 = new MockCountingWorkflow(new String[]{"i1", "i3"}, new String[]{"n1"});
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2", "i3"});
+		model.addDocument("doc2", "env2", "user2", new String[] {"i1", "i2"});
+		model.addWorkflow(cnt1);
+		assertEquals(2, cnt1.getInstances());
+		model.addWorkflow(cnt2);
+		assertEquals(1, cnt2.getInstances());
+		model.removeWorkflow(cnt1);
+		model.removeWorkflow(cnt2);
+
+		assertEquals(0, cnt1.getInstances());
+		assertEquals(0, cnt2.getInstances());
+	}	
+
+	@Test
+	public void testMatchingWorkflowAndRoute() {
+		MockCountingWorkflow cnt1 = new MockCountingWorkflow(new String[]{"i1"}, new String[]{"n1"});
+		MockCountingWorkflow cnt2 = new MockCountingWorkflow(new String[]{"i1", "i3"}, new String[]{"n1"});
+
+		model.addWorkflow(cnt1);
+
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2", "i3"});
+		assertEquals(1, cnt1.getInstances());
+		model.addWorkflow(cnt2);
+		assertEquals(1, cnt2.getInstances());
+				
+		model.addDocument("doc2", "env2", "user2", new String[] {"i1", "i2"});
+
+		assertEquals(2, cnt1.getInstances());
+		assertEquals(1, cnt2.getInstances());
+		model.removeWorkflow(cnt1);
+		model.removeWorkflow(cnt2);
+
+		assertEquals(0, cnt1.getInstances());
+		assertEquals(0, cnt2.getInstances());
+	}	
+
+	@Test
+	public void testRemovingRouteTwice() {
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2", "i3"});
+		model.removeDocument("doc1");
+		model.removeDocument("doc1");
+		assertEquals(0, model.getRoutes().size());		
+	}
+	
+	@Test
+	public void testWorkflowTwice() {
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2", "i3"});
+		MockCountingWorkflow cnt1 = new MockCountingWorkflow(new String[]{"i1"}, new String[]{"n1"});
+		model.removeWorkflow(cnt1);
+		model.removeWorkflow(cnt1);
+	}
+	
+	@Test
+	public void testStoppingAllRoutes() {
+		MockCountingWorkflow cnt1 = new MockCountingWorkflow(new String[]{"i1"}, new String[]{"n1"});
+		MockCountingWorkflow cnt2 = new MockCountingWorkflow(new String[]{"i1", "i3"}, new String[]{"n1"});
+		model.addDocument("doc1", "env1", "user1", new String[] {"i1", "i2", "i3"});
+		model.addDocument("doc2", "env2", "user2", new String[] {"i1", "i2"});
+		model.addWorkflow(cnt1);
+		model.addWorkflow(cnt2);
+
+		model.stopAllRoutes();
+		
+		assertEquals(0, cnt1.getInstances());
+		assertEquals(0, cnt2.getInstances());
+		assertEquals(0, model.getRoutes().size());
+	}	
+
+
+}
diff --git a/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockAbstractWorkflow.java b/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockAbstractWorkflow.java
new file mode 100644
index 0000000000000000000000000000000000000000..a85c97ed424e5fdee7e6acfb791b7aea24751d9b
--- /dev/null
+++ b/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockAbstractWorkflow.java
@@ -0,0 +1,31 @@
+package info.kwarc.sally4.docmanager.mocks;
+
+import info.kwarc.sally4.docmanager.AlexRoute;
+import info.kwarc.sally4.docmanager.IDocWorkflow;
+import info.kwarc.sally4.docmanager.IDocWorkflowInstance;
+
+public class MockAbstractWorkflow implements IDocWorkflow {
+	String [] ifaces;
+	String [] namespaces;
+	
+	public MockAbstractWorkflow(String [] ifaces, String [] namespaces) {
+		this.ifaces = ifaces;
+		this.namespaces = namespaces;
+	}
+	
+	@Override
+	public String[] getInterfaceRequirements() {
+		return ifaces;
+	}
+
+	@Override
+	public String[] getHandlingNamespaces() {
+		return namespaces;
+	}
+
+	@Override
+	public IDocWorkflowInstance createDocumentInstance(AlexRoute route) {
+		return null;
+	}
+
+}
diff --git a/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockCountingWorkflow.java b/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockCountingWorkflow.java
new file mode 100644
index 0000000000000000000000000000000000000000..5455b308c3a26ba95c4cae4ade4c88bf98af137f
--- /dev/null
+++ b/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockCountingWorkflow.java
@@ -0,0 +1,52 @@
+package info.kwarc.sally4.docmanager.mocks;
+
+import org.apache.camel.Exchange;
+
+import info.kwarc.sally4.docmanager.AlexRoute;
+import info.kwarc.sally4.docmanager.IDocWorkflow;
+import info.kwarc.sally4.docmanager.IDocWorkflowInstance;
+
+public class MockCountingWorkflow implements IDocWorkflow {
+	String [] ifaces;
+	String [] namespaces;
+	int instances;
+	
+	public MockCountingWorkflow(String [] ifaces, String [] namespaces) {
+		this.ifaces = ifaces;
+		this.namespaces = namespaces;
+		instances = 0;
+	}
+	
+	@Override
+	public String[] getInterfaceRequirements() {
+		return ifaces;
+	}
+
+	@Override
+	public String[] getHandlingNamespaces() {
+		return namespaces;
+	}
+	
+	public int getInstances() {
+		return instances;
+	}
+
+	@Override
+	public IDocWorkflowInstance createDocumentInstance(AlexRoute route) {
+		instances++;
+		return new IDocWorkflowInstance() {
+			
+			@Override
+			public void stop() {
+				instances--;
+			}
+			
+			@Override
+			public boolean handleMessage(AlexRoute route, String namespace,
+					String type, Exchange exchange) {
+				return false;
+			}
+		};
+	}
+
+}
diff --git a/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockGlobalContextProvider.java b/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockGlobalContextProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2b3362213f533c2f5a7a8248e475f9b1562f3dd
--- /dev/null
+++ b/docmanager/src/test/java/info/kwarc/sally4/docmanager/mocks/MockGlobalContextProvider.java
@@ -0,0 +1,32 @@
+package info.kwarc.sally4.docmanager.mocks;
+
+import info.kwarc.sally4.core.CamelContextProvider;
+
+import org.apache.camel.Component;
+import org.apache.camel.component.direct.DirectComponent;
+
+public class MockGlobalContextProvider implements CamelContextProvider {
+
+	@Override
+	public Component getComponent(String componentName) {
+		return new DirectComponent();
+	}
+
+	@Override
+	public void registerGlobalComponent(String componentName,
+			Component component) {
+		
+	}
+
+	@Override
+	public void unregisterGlobalComponent(String componentName) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public String getName() {
+		return "mockery";
+	}
+
+}
diff --git a/utils/src/main/java/info/kwarc/sally4/processors/EnrichMessageProperties.java b/utils/src/main/java/info/kwarc/sally4/processors/EnrichMessageProperties.java
index f56a3550bc591e5cae7391e9548a3380ad58f7fd..3e27ff2350556540a095e1acdbcc6cdd7d9f12a8 100644
--- a/utils/src/main/java/info/kwarc/sally4/processors/EnrichMessageProperties.java
+++ b/utils/src/main/java/info/kwarc/sally4/processors/EnrichMessageProperties.java
@@ -17,12 +17,15 @@ public class EnrichMessageProperties implements Processor {
 	Pattern xmlNamespace = Pattern.compile("<(\\w+)\\s+xmlns=\"([\\w/:.]+)\"/>");
 		
 	public void process(Exchange exchange) throws Exception {
-		Matcher m = xmlNamespace.matcher(exchange.getIn().getBody(String.class));
+		XMLMessageWithTypeInfo result = new XMLMessageWithTypeInfo();
+		String body = exchange.getIn().getBody(String.class);
+		Matcher m = xmlNamespace.matcher(body);
 		if (m.find()) {
 			String msgType = m.group(1);
 			String namespace = m.group(2);
-			exchange.getIn().setHeader(MessageType, msgType);
-			exchange.getIn().setHeader(MessageNamespace, namespace);
+			result.setXmlMessageNamespace(namespace);
+			result.setXmlMessageType(msgType);
+			exchange.getIn().setBody(result);
 		} else {
 			exchange.setException(new Exception("Could not detect namespace in incoming message"));
 		}
diff --git a/utils/src/main/java/info/kwarc/sally4/processors/TypedCallback.java b/utils/src/main/java/info/kwarc/sally4/processors/TypedCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d1f87f50e7004f360d05396b0989230d7e057b7
--- /dev/null
+++ b/utils/src/main/java/info/kwarc/sally4/processors/TypedCallback.java
@@ -0,0 +1,5 @@
+package info.kwarc.sally4.processors;
+
+public interface TypedCallback<T> {
+	void run(T obj);
+}
diff --git a/utils/src/main/java/info/kwarc/sally4/processors/XMLMessageWithTypeInfo.java b/utils/src/main/java/info/kwarc/sally4/processors/XMLMessageWithTypeInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..041e8ac9510d51c52cd468e7656600fa98f21e22
--- /dev/null
+++ b/utils/src/main/java/info/kwarc/sally4/processors/XMLMessageWithTypeInfo.java
@@ -0,0 +1,32 @@
+package info.kwarc.sally4.processors;
+
+import org.apache.camel.Exchange;
+
+public class XMLMessageWithTypeInfo {
+	Exchange exchange;
+	String xmlMessageType;
+	String xmlMessageNamespace;
+
+	public XMLMessageWithTypeInfo() {
+	}
+
+	public Exchange getExchange() {
+		return exchange;
+	}
+	public void setExchange(Exchange exchange) {
+		this.exchange = exchange;
+	}
+	public String getXmlMessageType() {
+		return xmlMessageType;
+	}
+	public void setXmlMessageType(String xmlMessageType) {
+		this.xmlMessageType = xmlMessageType;
+	}
+
+	public String getXmlMessageNamespace() {
+		return xmlMessageNamespace;
+	}
+	public void setXmlMessageNamespace(String xmlMessageNamespace) {
+		this.xmlMessageNamespace = xmlMessageNamespace;
+	}
+}