diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 70f955c066941e1f22918595675270a4c5570ae2..898917dc6d63e885dc03d9801253bcafe665a365 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,11 +3,11 @@ variables:
   GIT_DEPTH: 1000
 
 stages:
-  - build
-  - test
-  - ragdoc_build
-  - ragdoc_view
-  - publish
+- build
+- test
+#- ragdoc_build
+#- ragdoc_view
+#- publish
 
 before_script:
   - export GRADLE_USER_HOME=`pwd`/.gradle
@@ -44,64 +44,64 @@ test:
       junit: "ragconnect.tests/build/test-results/**/TEST-*.xml"
     expire_in: 1 week
 
-publish:
-  image: openjdk:11
-  stage: publish
-  needs:
-    - test
-  script:
-    - "./gradlew publish"
-  only:
-    - dev
-    - master
+#publish:
+#  image: openjdk:11
+#  stage: publish
+#  needs:
+#    - test
+#  script:
+#    - "./gradlew publish"
+#  only:
+#    - dev
+#    - master
 
-ragdoc_build:
-  image:
-    name: "git-st.inf.tu-dresden.de:4567/jastadd/ragdoc-builder"
-    entrypoint: [""]
-  stage: ragdoc_build
-  needs:
-    - build
-  script:
-    - JAVA_FILES=$(find ragconnect.base/src/ -name '*.java')
-    - /ragdoc-builder/start-builder.sh -excludeGenerated -d data/ $JAVA_FILES
-  artifacts:
-    paths:
-      - "data/"
+#ragdoc_build:
+#  image:
+#    name: "git-st.inf.tu-dresden.de:4567/jastadd/ragdoc-builder"
+#    entrypoint: [""]
+#  stage: ragdoc_build
+#  needs:
+#    - build
+#  script:
+#    - JAVA_FILES=$(find ragconnect.base/src/ -name '*.java')
+#    - /ragdoc-builder/start-builder.sh -excludeGenerated -d data/ $JAVA_FILES
+#  artifacts:
+#    paths:
+#      - "data/"
 
-ragdoc_view:
-  image:
-    name: "git-st.inf.tu-dresden.de:4567/jastadd/ragdoc-view:relations"
-    entrypoint: [""]
-  stage: ragdoc_view
-  needs:
-    - ragdoc_build
-  script:
-    - DATA_DIR=$(pwd -P)/data
-    - mkdir -p pages/docs/ragdoc
-    - OUTPUT_DIR=$(pwd -P)/pages/docs/ragdoc
-    - cd /ragdoc-view/src/ && rm -rf data && ln -s $DATA_DIR
-    - /ragdoc-view/build-view.sh --output-path=$OUTPUT_DIR
-  only:
-    - dev
-    - master
-  artifacts:
-    paths:
-      - "pages/docs/ragdoc"
+#ragdoc_view:
+#  image:
+#    name: "git-st.inf.tu-dresden.de:4567/jastadd/ragdoc-view:relations"
+#    entrypoint: [""]
+#  stage: ragdoc_view
+#  needs:
+#    - ragdoc_build
+#  script:
+#    - DATA_DIR=$(pwd -P)/data
+#    - mkdir -p pages/docs/ragdoc
+#    - OUTPUT_DIR=$(pwd -P)/pages/docs/ragdoc
+#    - cd /ragdoc-view/src/ && rm -rf data && ln -s $DATA_DIR
+#    - /ragdoc-view/build-view.sh --output-path=$OUTPUT_DIR
+#  only:
+#    - dev
+#    - master
+#  artifacts:
+#    paths:
+#     - "pages/docs/ragdoc"
 
-pages:
-  image: python:3.8-buster
-  stage: publish
-  needs:
-    - ragdoc_view
-    - test
-  before_script:
-    - pip install -U mkdocs mkdocs-macros-plugin mkdocs-git-revision-date-localized-plugin
-  script:
-    - cd pages && mkdocs build
-  only:
-    - dev
-    - master
-  artifacts:
-    paths:
-    - public
+#pages:
+#  image: python:3.8-buster
+# stage: publish
+# needs:
+#   - ragdoc_view
+#    - test
+# before_script:
+#   - pip install -U mkdocs mkdocs-macros-plugin mkdocs-git-revision-date-localized-plugin
+#  script:
+#   - cd pages && mkdocs build
+#only:
+#  - dev
+#    - master
+#artifacts:
+# paths:
+#  - public
diff --git a/.gitmodules b/.gitmodules
index 58efd108e858ae06dde5f626286bd3d73f9dde4e..14c250a57ed1d3278b5d6ce961c8fae45e9266cb 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,3 +2,6 @@
 	path = relast-preprocessor
 	url = ../relast-preprocessor.git
 	branch = develop
+[submodule "ragconnect.base/src/main/jastadd/mustache"]
+	path = ragconnect.base/src/main/jastadd/mustache
+	url = git@git-st.inf.tu-dresden.de:jastadd/jastadd-ceti/mustache.git
diff --git a/ragconnect.base/build.gradle b/ragconnect.base/build.gradle
index 671556c463b40a4224cc70df5ad1db0340858ee5..753814f384186d096929fd2794ac6a19129bfb1f 100644
--- a/ragconnect.base/build.gradle
+++ b/ragconnect.base/build.gradle
@@ -28,6 +28,9 @@ repositories {
 dependencies {
     implementation project(':relast-preprocessor')
     implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "${mustache_java_version}"
+    // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
+    api group: 'org.apache.commons', name: 'commons-lang3', version: '3.0'
+    runtimeOnly group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
 //    runtimeOnly group: 'org.jastadd', name: 'jastadd', version: '2.3.5'
     runtimeOnly fileTree(include: ['jastadd2.jar'], dir: '../libs')
     api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
diff --git a/ragconnect.base/src/main/jastadd/Configuration.jadd b/ragconnect.base/src/main/jastadd/Configuration.jadd
index 8fd0e64b14bbd9a05c7cbf9b7de59ed0cd216d78..8c7213850afc5471c70c215d5462442b7da32326 100644
--- a/ragconnect.base/src/main/jastadd/Configuration.jadd
+++ b/ragconnect.base/src/main/jastadd/Configuration.jadd
@@ -6,6 +6,7 @@ aspect Configuration {
   public static String ASTNode.JastAddList = "List";
   public static boolean ASTNode.usesMqtt;
   public static boolean ASTNode.usesRest;
+  public static boolean ASTNode.usesJava;
   public static boolean ASTNode.incrementalOptionActive;
   public static boolean ASTNode.experimentalJastAdd329;
 }
diff --git a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd
index 7e4bde916d565d16bdef34598d638d2080f2f5fa..7a09e6547c1ce7c635e2d2f37f9d7db77248ae68 100644
--- a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd
+++ b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd
@@ -18,6 +18,9 @@ aspect AttributesForMustache {
   syn String MRagConnect.restHandlerAttribute() = "_restHandler";
   syn String MRagConnect.restHandlerField() = "_restHandler";
 
+  syn String MRagConnect.javaHandlerAttribute() = "_javaHandler";
+  syn String MRagConnect.javaHandlerField() = "_javaHandler";
+
   syn boolean MRagConnect.hasTreeListEndpoints() = !sendingTreeListEndpoints().isEmpty() || !receivingTreeListEndpoints().isEmpty();
   syn List<MTypeEndpointDefinition> MRagConnect.sendingTreeListEndpoints() {
     List<MTypeEndpointDefinition> result = new ArrayList<>();
@@ -254,6 +257,8 @@ aspect AttributesForMustache {
                                    result.mqttHandlerAttribute(), result.mqttHandlerField(), usesMqtt));
     result.addHandler(new MHandler("RestServerHandler", "new RestServerHandler(\"RagConnectREST\")",
                                    result.restHandlerAttribute(), result.restHandlerField(), usesRest));
+    result.addHandler(new MHandler("JavaHandler", "JavaHandler.getInstance()",
+        result.javaHandlerAttribute(), result.javaHandlerField(), usesJava));
     return result;
   }
 
diff --git a/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag b/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag
index 04b9cf89c248c39740677c88835b56c5325493bf..bd3afcd607a3be9757ec920251d48080fccd1901 100644
--- a/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag
+++ b/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag
@@ -6,11 +6,17 @@ aspect MustacheNodesToYAML {
     root.put("closeMethod", closeMethod());
     root.put("usesMqtt", usesMqtt);
     root.put("usesRest", usesRest);
+    root.put("usesJava", usesJava);
+
     // mqtt
     root.put("mqttHandlerField", mqttHandlerField());
     root.put("mqttHandlerAttribute", mqttHandlerAttribute());
     root.put("mqttSetupWaitUntilReadyMethod", mqttSetupWaitUntilReadyMethod());
 
+    // java
+    root.put("javaHandlerField", javaHandlerField());
+    root.put("javaHandlerAttribute", javaHandlerAttribute());
+
     // rootTypeComponents
     ListElement rootTypeComponents = new ListElement();
     for (MTypeComponent comp : getRootTypeComponentList()) {
diff --git a/ragconnect.base/src/main/jastadd/mustache b/ragconnect.base/src/main/jastadd/mustache
new file mode 160000
index 0000000000000000000000000000000000000000..c10bed0d03e3fa18b8133ce1de48de7646899615
--- /dev/null
+++ b/ragconnect.base/src/main/jastadd/mustache
@@ -0,0 +1 @@
+Subproject commit c10bed0d03e3fa18b8133ce1de48de7646899615
diff --git a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java
index 915d9f92d49cf3a847f05d0b23393bce1832fc1a..c16c6261b688eb6e784c9c8954578d81f0b8cd24 100644
--- a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java
+++ b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java
@@ -32,6 +32,7 @@ public class Compiler extends AbstractCompiler {
 
   private static final String OPTION_PROTOCOL_MQTT = "mqtt";
   private static final String OPTION_PROTOCOL_REST = "rest";
+  private static final String OPTION_PROTOCOL_JAVA = "java";
 
   private final static Logger LOGGER = Logger.getLogger(Compiler.class.getName());
 
@@ -69,6 +70,18 @@ public class Compiler extends AbstractCompiler {
 
     RagConnect ragConnect = parseProgram(getConfiguration().getFiles());
 
+    // lets inspect ragconnects tree
+    /*
+    for(EndpointDefinition ed : ragConnect.getEndpointDefinitionList()){
+      if(ed.isReceiveTokenEndpointDefinition()){
+        for(MappingDefinition md : ed.asReceiveTokenEndpointDefinition().effectiveMappings()){
+          //     if (!effectiveMappings().get(effectiveMappings().size() - 1).getToType().assignableTo(
+          //              getToken().effectiveJavaTypeUse())) {
+          System.out.println("gtt: " + md.getToType());
+        }
+      }
+    }
+    */
     if (!ragConnect.errors().isEmpty()) {
       StringBuilder sb = new StringBuilder("Errors:\n");
       for (ErrorMessage e : ragConnect.errors()) {
@@ -91,6 +104,9 @@ public class Compiler extends AbstractCompiler {
     if (ASTNode.usesMqtt) {
       handlers.add("MqttHandler.jadd");
     }
+    if (ASTNode.usesJava) {
+      handlers.add("JavaHandler.jadd");
+    }
     if (ASTNode.usesRest) {
       handlers.add("RestHandler.jadd");
     }
@@ -163,8 +179,9 @@ public class Compiler extends AbstractCompiler {
     optionProtocols = addOption(
         new ValueOption("protocols", "Protocols to enable")
         .acceptMultipleValues(true)
-        .addDefaultValue(OPTION_PROTOCOL_MQTT, "Enable MQTT")
+        .addDefaultValue(OPTION_PROTOCOL_JAVA, "Enable Java")
         .addAcceptedValue(OPTION_PROTOCOL_REST, "Enable REST")
+        .addAcceptedValue(OPTION_PROTOCOL_MQTT, "Enable MQTT")
     );
     optionPrintYaml = addOption(
         new BooleanOption("printYaml", "Print out YAML instead of generating files")
@@ -246,6 +263,7 @@ public class Compiler extends AbstractCompiler {
     ASTNode.JastAddList = getConfiguration().listType();
 
     ASTNode.usesMqtt = optionProtocols.hasValue(OPTION_PROTOCOL_MQTT);
+    ASTNode.usesJava = optionProtocols.hasValue(OPTION_PROTOCOL_JAVA);
     ASTNode.usesRest = optionProtocols.hasValue(OPTION_PROTOCOL_REST);
     return ragConnect;
   }
diff --git a/ragconnect.base/src/main/resources/JavaHandler.jadd b/ragconnect.base/src/main/resources/JavaHandler.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..5849b61fb221752c21e00795cb5494c43f18ef51
--- /dev/null
+++ b/ragconnect.base/src/main/resources/JavaHandler.jadd
@@ -0,0 +1,101 @@
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
+
+aspect JavaHandler {
+
+    /**
+     * Singleton class providing routing functionality for byte[] based message calls.
+     */
+    public class JavaHandler {
+
+        public static JavaHandler JAVA_HANDLER_INSTANCE = null;
+
+        private final org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getLogger(JavaHandler.class);
+
+        private Map<String, List<org.apache.commons.lang3.tuple.Pair<String, Consumer<byte[]>>>> callbackList = new ConcurrentHashMap<>();
+
+        private JavaHandler() {
+
+        }
+
+        public synchronized static JavaHandler getInstance() {
+            if(JAVA_HANDLER_INSTANCE == null) {
+                JAVA_HANDLER_INSTANCE = new JavaHandler();
+            }
+            return JAVA_HANDLER_INSTANCE;
+        }
+
+        public String registerCallback(String topic, Consumer<byte[]> callback) {
+
+            logger.debug("[JAVA_HANDLER] Registering new callback.");
+
+            String callbackUUID = java.util.UUID.randomUUID().toString();
+
+            List<org.apache.commons.lang3.tuple.Pair<String, Consumer<byte[]>>> registeredCallbacks = getAllCallbacks().get(topic);
+
+            if(registeredCallbacks == null){
+                List<org.apache.commons.lang3.tuple.Pair<String, Consumer<byte[]>>> newCallbackList = Collections.synchronizedList(new ArrayList<>());
+                newCallbackList.add(new org.apache.commons.lang3.tuple.MutablePair<>(callbackUUID, callback));
+                callbackList.put(topic, newCallbackList);
+            } else {
+                registeredCallbacks.add(new org.apache.commons.lang3.tuple.MutablePair<>(callbackUUID, callback));
+            }
+
+            return callbackUUID;
+        }
+
+        public boolean unregisterCallback(String path, String uuid){
+
+            logger.debug("[JAVA_HANDLER] Unregistering callback with uuid: " + uuid + " on path: " + path);
+
+            List<org.apache.commons.lang3.tuple.Pair<String, Consumer<byte[]>>> callbacks = getAllCallbacks().get(path);
+
+            int count = 0;
+
+            if(callbacks != null){
+                for(org.apache.commons.lang3.tuple.Pair<String, Consumer<byte[]>> callbackPair : callbacks){
+                    if(callbackPair.getLeft().equals(uuid)){
+                        callbacks.remove(count);
+                        return true;
+                    }else{
+                        count++;
+                    }
+                }
+            }
+            return false;
+        }
+
+        public void close(){};
+
+        public boolean push(String topic, byte[] data) {
+
+            logger.info("[JAVA_HANDLER] Pushing a message.");
+
+            String dataString = new String(data);
+
+            logger.info("[JAVA_HANDLER] Data: " + dataString);
+
+            List<org.apache.commons.lang3.tuple.Pair<String, Consumer<byte[]>>> callbacks = getAllCallbacks().get(topic);
+
+            if(callbacks == null){
+                logger.error("[JAVA_HANDLER] Could not publish message. No callback registered for topic " + topic);
+                return false;
+            }
+
+            for(org.apache.commons.lang3.tuple.Pair<String, Consumer<byte[]>> callbackPair : callbacks){
+                logger.debug("[JAVA_HANDLER] Calling callback: " + callbackPair.getLeft());
+                callbackPair.getRight().accept(data);
+            }
+
+            return true;
+        }
+
+        public Map<String, List<org.apache.commons.lang3.tuple.Pair<String, Consumer<byte[]>>>> getAllCallbacks() {
+            return callbackList;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ragconnect.base/src/main/resources/handler.mustache b/ragconnect.base/src/main/resources/handler.mustache
index 41e42387f69239f054b8ddaafa80680b13ca7591..896f6ac8dd7befc02d67ce3a2863c45f0822e0c1 100644
--- a/ragconnect.base/src/main/resources/handler.mustache
+++ b/ragconnect.base/src/main/resources/handler.mustache
@@ -1,3 +1,4 @@
+
 aspect RagConnectHandler {
 {{#Handlers}}
   {{#InUse}}
@@ -15,14 +16,19 @@ aspect RagConnectHandler {
     {{/Handlers}}
   }
   class ConnectToken {
-    static java.util.concurrent.atomic.AtomicLong counter = new java.util.concurrent.atomic.AtomicLong(0);
-    final long id;
+    //static java.util.concurrent.atomic.AtomicLong counter = new java.util.concurrent.atomic.AtomicLong(0);
+    final String id;
     final java.net.URI uri;
+
     public ConnectToken(java.net.URI uri) {
-      this.id = counter.incrementAndGet();
+      this.id = java.util.UUID.randomUUID().toString(); // counter.incrementAndGet();
       this.uri = uri;
     }
 
+    public ConnectToken(java.net.URI uri, String uuid) {
+        this.id = uuid; // counter.incrementAndGet();
+        this.uri = uri;
+    }
   }
   static java.util.Map<ASTNode, java.util.Map<java.net.URI, ConnectToken>> ASTNode.connectTokens = new java.util.HashMap<>();
 }
diff --git a/ragconnect.base/src/main/resources/receiveDefinition.mustache b/ragconnect.base/src/main/resources/receiveDefinition.mustache
index 4ae8a05c6f97e03f5522160a487f33a710186a2c..9a8e309964319ee768879aa9f0c4b6a6b9d316a4 100644
--- a/ragconnect.base/src/main/resources/receiveDefinition.mustache
+++ b/ragconnect.base/src/main/resources/receiveDefinition.mustache
@@ -109,6 +109,15 @@ private boolean {{parentTypeName}}.{{internalConnectMethod}}(String {{connectPar
       }
       break;
   {{/usesMqtt}}
+  {{#usesJava}}
+    case "java":
+        String uuid = {{javaHandlerAttribute}}().registerCallback(path, consumer);
+        connectToken = new ConnectToken(uri, uuid);
+        if (uuid == null) {
+            return false;
+        }
+        break;
+  {{/usesJava}}
   {{#usesRest}}
     case "rest":
       connectToken = {{restHandlerAttribute}}().newPUTConnection(uri, input -> {
@@ -135,6 +144,9 @@ public boolean {{parentTypeName}}.{{disconnectMethod}}(String {{connectParameter
   {{#usesMqtt}}
     case "mqtt": return {{mqttHandlerAttribute}}().disconnect(connectTokens.get(this).get(uri));
   {{/usesMqtt}}
+  {{#usesJava}}
+      case "java": return {{javaHandlerAttribute}}().unregisterCallback(uri.getPath(), connectTokens.get(this).get(uri).id);
+  {{/usesJava}}
   {{#usesRest}}
     case "rest": return {{restHandlerAttribute}}().disconnect(connectTokens.get(this).get(uri));
   {{/usesRest}}
diff --git a/ragconnect.base/src/main/resources/sendDefinition.mustache b/ragconnect.base/src/main/resources/sendDefinition.mustache
index 6fd97bf2cc7154cd0d053311f95166347cbccc6a..bf05fadf4c4c8281aea696425b2982617eec2029 100644
--- a/ragconnect.base/src/main/resources/sendDefinition.mustache
+++ b/ragconnect.base/src/main/resources/sendDefinition.mustache
@@ -27,6 +27,19 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam
       connectToken = new ConnectToken(uri);
       break;
   {{/usesMqtt}}
+  {{#usesJava}}
+      case "java":
+      final JavaHandler handler = {{javaHandlerAttribute}}().getInstance();
+
+      {{sender}} = () -> {
+        handler.push(path, {{lastValue}});
+      };
+    {{updateMethod}}();
+    if (writeCurrentValue) {
+      {{writeMethod}}();
+    }
+    break;
+  {{/usesJava}}
   {{#usesRest}}
     case "rest":
       connectToken = {{restHandlerAttribute}}().newGETConnection(uri, () -> {
@@ -70,6 +83,11 @@ public boolean {{parentTypeName}}.{{disconnectMethod}}(String {{connectParameter
       {{lastValue}} = null;
       break;
   {{/usesMqtt}}
+  {{#usesJava}}
+      case "java":
+      // nothing todo, because senders are not registered (just callbacks)
+      break;
+  {{/usesJava}}
   {{#usesRest}}
     case "rest":
       {{restHandlerAttribute}}().disconnect(connectToken);
diff --git a/ragconnect.tests/build.gradle b/ragconnect.tests/build.gradle
index 61470f5292531d0ec7ca5d3691a3b248bcff1588..c43e47044c47358624b646fec196634ac28786bf 100644
--- a/ragconnect.tests/build.gradle
+++ b/ragconnect.tests/build.gradle
@@ -562,3 +562,4 @@ task compileSingleListVariantIncremental(type: RagConnectTest, dependsOn: ':ragc
 //}
 //compileSingleListVariantManual.dependsOn cleanCurrentManualTest
 //compileSingleListVariantIncremental.dependsOn cleanCurrentIncrementalTest
+
diff --git a/relast-preprocessor b/relast-preprocessor
index 02f8e35993dc3f62ab49e94f69a6dc27170660da..c00441c03dc6723a08de0fcb041254a99497774f 160000
--- a/relast-preprocessor
+++ b/relast-preprocessor
@@ -1 +1 @@
-Subproject commit 02f8e35993dc3f62ab49e94f69a6dc27170660da
+Subproject commit c00441c03dc6723a08de0fcb041254a99497774f