Merge branch 'dev' into STREAMPIPES-527
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index af9fb37..f6eea9e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -114,6 +114,14 @@
           push: true
           tags: ${{ env.DOCKERHUB_APACHE_REPO }}/pipeline-elements-all-flink:${{ env.MVN_VERSION }}
 
+      - name: Build and Push Docker Image extensions-all-iiot
+        uses: docker/build-push-action@v2
+        with:
+          context: ./streampipes-extensions/streampipes-extensions-all-iiot
+          platforms: linux/amd64,linux/arm64/v8,linux/arm/v7
+          push: true
+          tags: ${{ env.DOCKERHUB_APACHE_REPO }}/extensions-all-iiot:${{ env.MVN_VERSION }}
+
       - name: Build and Push Docker Image pipeline-elements-all-jvm
         uses: docker/build-push-action@v2
         with:
@@ -122,10 +130,11 @@
           push: true
           tags: ${{ env.DOCKERHUB_APACHE_REPO }}/pipeline-elements-all-jvm:${{ env.MVN_VERSION }}
 
-      - name: Build and Push Docker Image sinks-internal-jvm
+      - name: Build and Push Docker Image sources-watertank-simulator
         uses: docker/build-push-action@v2
         with:
-          context: ./streampipes-extensions/streampipes-sinks-internal-jvm
+          context: ./streampipes-extensions/streampipes-sources-watertank-simulator
           platforms: linux/amd64,linux/arm64/v8,linux/arm/v7
           push: true
-          tags: ${{ env.DOCKERHUB_APACHE_REPO }}/sinks-internal-jvm:${{ env.MVN_VERSION }}
\ No newline at end of file
+          tags: ${{ env.DOCKERHUB_APACHE_REPO }}/sources-watertank-simulator:${{ env.MVN_VERSION }}
+
diff --git a/.gitignore b/.gitignore
index 4b3258f..324db87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -83,7 +83,7 @@
 /test_data/
 
 ui/src/assets/lib/apps/*
-
+ui/.angular
 
 # compiled output
 ui/dist
diff --git a/.idea/runConfigurations/all_extensions_jvm.xml b/.idea/runConfigurations/all_extensions_jvm.xml
index 20063d0..103f85d 100644
--- a/.idea/runConfigurations/all_extensions_jvm.xml
+++ b/.idea/runConfigurations/all_extensions_jvm.xml
@@ -1,14 +1,14 @@
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="all-extensions-jvm" type="Application" factoryName="Application">
     <envs>
-      <env name="SP_PORT" value="7023" />
-      <env name="SP_DEBUG" value="true" />
       <env name="SP_COUCHDB_HOST" value="localhost" />
-      <env name="SP_JMS_HOST" value="localhost" />
-      <env name="SP_JMS_PORT" value="61616" />
       <env name="SP_DATA_LAKE_HOST" value="localhost" />
       <env name="SP_DATA_LAKE_PORT" value="8086" />
+      <env name="SP_DEBUG" value="true" />
       <env name="SP_IMAGE_STORAGE_LOCATION" value=".streampipes/spImages/" />
+      <env name="SP_JMS_HOST" value="localhost" />
+      <env name="SP_JMS_PORT" value="61616" />
+      <env name="SP_PORT" value="7023" />
     </envs>
     <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.extensions.all.jvm.AllExtensionsInit" />
     <module name="streampipes-extensions-all-jvm" />
@@ -27,4 +27,4 @@
       <option name="Make" enabled="true" />
     </method>
   </configuration>
-</component>
\ No newline at end of file
+</component>
diff --git a/.idea/runConfigurations/all_pipeline_elements_jvm.xml b/.idea/runConfigurations/all_pipeline_elements_jvm.xml
index 08521f8..60c64ea 100644
--- a/.idea/runConfigurations/all_pipeline_elements_jvm.xml
+++ b/.idea/runConfigurations/all_pipeline_elements_jvm.xml
@@ -1,7 +1,5 @@
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="all-pipeline-elements-jvm" type="Application" factoryName="Application">
-    <option name="ALTERNATIVE_JRE_PATH" value="/Library/Java/JavaVirtualMachines/jdk-17.0.1.jdk/Contents/Home" />
-    <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
     <envs>
       <env name="SP_PORT" value="7023" />
       <env name="SP_DEBUG" value="true" />
diff --git a/.idea/runConfigurations/backend.xml b/.idea/runConfigurations/backend.xml
index fb5908b..344ff6e 100644
--- a/.idea/runConfigurations/backend.xml
+++ b/.idea/runConfigurations/backend.xml
@@ -1,20 +1,19 @@
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="backend" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
-    <module name="streampipes-backend" />
-    <option name="SPRING_BOOT_MAIN_CLASS" value="org.apache.streampipes.backend.StreamPipesBackendApplication" />
-    <option name="ALTERNATIVE_JRE_PATH" value="11" />
-    <option name="SHORTEN_COMMAND_LINE" value="NONE" />
+    <option name="ACTIVE_PROFILES" />
     <envs>
-      <env name="SP_COUCHDB_HOST" value="localhost" />
       <env name="SP_BACKEND_HOST" value="localhost" />
+      <env name="SP_COUCHDB_HOST" value="localhost" />
+      <env name="SP_DEBUG" value="true " />
       <env name="SP_INFLUX_HOST" value="localhost" />
-      <env name="SP_KAFKA_HOST" value="localhost" />
       <env name="SP_INFLUX_PORT" value="8086" />
-      <env name="SP_KAFKA_PORT" value="9094" />
       <env name="SP_JMS_HOST" value="localhost" />
-      <env name="SP_DEBUG" value="true" />
+      <env name="SP_KAFKA_HOST" value="localhost" />
+      <env name="SP_KAFKA_PORT" value="9094" />
       <env name="SP_PRIORITIZED_PROTOCOL" value="mqtt" />
     </envs>
+    <module name="streampipes-backend" />
+    <option name="SPRING_BOOT_MAIN_CLASS" value="org.apache.streampipes.backend.StreamPipesBackendApplication" />
     <method v="2">
       <option name="Make" enabled="true" />
     </method>
diff --git a/.idea/runConfigurations/processors_aggregation_flink.xml b/.idea/runConfigurations/processors_aggregation_flink.xml
deleted file mode 100644
index 183a887..0000000
--- a/.idea/runConfigurations/processors_aggregation_flink.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-aggregation-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6005" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.aggregation.flink.AggregationFlinkInit" />
-    <module name="streampipes-processors-aggregation-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_enricher_flink.xml b/.idea/runConfigurations/processors_enricher_flink.xml
deleted file mode 100644
index 274dfd1..0000000
--- a/.idea/runConfigurations/processors_enricher_flink.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-enricher-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6010" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.enricher.flink.EnricherFlinkInit" />
-    <module name="streampipes-processors-enricher-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_enricher_jvm.xml b/.idea/runConfigurations/processors_enricher_jvm.xml
deleted file mode 100644
index ae43ed6..0000000
--- a/.idea/runConfigurations/processors_enricher_jvm.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-enricher-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6015" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.enricher.jvm.EnricherJvmInit" />
-    <module name="streampipes-processors-enricher-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_filters_jvm.xml b/.idea/runConfigurations/processors_filters_jvm.xml
deleted file mode 100644
index b504325..0000000
--- a/.idea/runConfigurations/processors_filters_jvm.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-filters-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6025" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.filters.jvm.FiltersJvmInit" />
-    <module name="streampipes-processors-filters-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_filters_siddhi.xml b/.idea/runConfigurations/processors_filters_siddhi.xml
deleted file mode 100644
index 6b060b6..0000000
--- a/.idea/runConfigurations/processors_filters_siddhi.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-filters-siddhi" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6025" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.siddhi.FiltersSiddhiInit" />
-    <module name="streampipes-processors-filters-siddhi" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_geo_flink.xml b/.idea/runConfigurations/processors_geo_flink.xml
deleted file mode 100644
index 5e89134..0000000
--- a/.idea/runConfigurations/processors_geo_flink.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-geo-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6025" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processor.geo.flink.GeoFlinkInit" />
-    <module name="streampipes-processors-geo-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_geo_jvm.xml b/.idea/runConfigurations/processors_geo_jvm.xml
deleted file mode 100644
index 78165cd..0000000
--- a/.idea/runConfigurations/processors_geo_jvm.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-geo-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="8005" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.geo.jvm.GeoJvmInit" />
-    <module name="streampipes-processors-geo-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_imageprocessing_jvm.xml b/.idea/runConfigurations/processors_imageprocessing_jvm.xml
deleted file mode 100644
index bb2e7b5..0000000
--- a/.idea/runConfigurations/processors_imageprocessing_jvm.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-imageprocessing-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6035" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.imageprocessing.jvm.ImageProcessingJvmInit" />
-    <module name="streampipes-processors-image-processing-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_pattern_detection_flink.xml b/.idea/runConfigurations/processors_pattern_detection_flink.xml
deleted file mode 100644
index 8ed0376..0000000
--- a/.idea/runConfigurations/processors_pattern_detection_flink.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-pattern-detection-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6040" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.pattern.detection.flink.PatternDetectionFlinkInit" />
-    <module name="streampipes-processors-pattern-detection-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_statistics_flink.xml b/.idea/runConfigurations/processors_statistics_flink.xml
deleted file mode 100644
index e9b74c8..0000000
--- a/.idea/runConfigurations/processors_statistics_flink.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-statistics-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6045" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.statistics.flink.StatisticsFlinkInit" />
-    <module name="streampipes-processors-statistics-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_textmining_flink.xml b/.idea/runConfigurations/processors_textmining_flink.xml
deleted file mode 100644
index 18a4204..0000000
--- a/.idea/runConfigurations/processors_textmining_flink.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-textmining-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6050" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.textmining.flink.TextMiningFlinkInit" />
-    <module name="streampipes-processors-text-mining-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_textmining_jvm.xml b/.idea/runConfigurations/processors_textmining_jvm.xml
deleted file mode 100644
index 4fb63c4..0000000
--- a/.idea/runConfigurations/processors_textmining_jvm.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-textmining-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6065" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.textmining.jvm.TextMiningJvmInit" />
-    <module name="streampipes-processors-text-mining-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_transformation_flink.xml b/.idea/runConfigurations/processors_transformation_flink.xml
deleted file mode 100644
index 456b92c..0000000
--- a/.idea/runConfigurations/processors_transformation_flink.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-transformation-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6055" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.transformation.flink.TransformationFlinkInit" />
-    <module name="streampipes-processors-transformation-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/processors_transformation_jvm.xml b/.idea/runConfigurations/processors_transformation_jvm.xml
deleted file mode 100644
index bfa0fff..0000000
--- a/.idea/runConfigurations/processors_transformation_jvm.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="processors-transformation-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="6060" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.processors.transformation.jvm.TransformationJvmInit" />
-    <module name="streampipes-processors-transformation-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/sinks_brokers_jvm.xml b/.idea/runConfigurations/sinks_brokers_jvm.xml
deleted file mode 100644
index bb2962d..0000000
--- a/.idea/runConfigurations/sinks_brokers_jvm.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="sinks-brokers-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="7005" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.sinks.brokers.jvm.BrokersJvmInit" />
-    <module name="streampipes-sinks-brokers-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/sinks_databases_flink.xml b/.idea/runConfigurations/sinks_databases_flink.xml
deleted file mode 100644
index e0ec58c..0000000
--- a/.idea/runConfigurations/sinks_databases_flink.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="sinks-databases-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="7010" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-      <env name="SP_ELASTICSEARCH_HOST" value="localhost" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.sinks.databases.flink.DatabasesFlinkInit" />
-    <module name="streampipes-sinks-databases-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/sinks_databases_jvm.xml b/.idea/runConfigurations/sinks_databases_jvm.xml
deleted file mode 100644
index 358b372..0000000
--- a/.idea/runConfigurations/sinks_databases_jvm.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="sinks-databases-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="7015" />
-      <env name="SP_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.sinks.databases.jvm.DatabasesJvmInit" />
-    <module name="streampipes-sinks-databases-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/sinks_notifications_jvm.xml b/.idea/runConfigurations/sinks_notifications_jvm.xml
deleted file mode 100644
index 77748b2..0000000
--- a/.idea/runConfigurations/sinks_notifications_jvm.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="sinks-notifications-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="7025" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SLACK_TOKEN" value="" />
-      <env name="EMAIL_FROMS" value="" />
-      <env name="EMAIL_USERNAME" value="" />
-      <env name="EMAIL_PASSWORD" value="" />
-      <env name="EMAIL_SMTP_HOST" value="" />
-      <env name="EMAIL_SMTP_PORT" value="" />
-      <env name="EMAIL_STARTTLS" value="" />
-      <env name="EMAIL_SILL" value="" />
-      <env name="WEBSOCKET_PROTOCOL" value="ws" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.sinks.notifications.jvm.SinksNotificationsJvmInit" />
-    <module name="streampipes-sinks-notifications-jvm" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/Jenkinsfile b/Jenkinsfile
index 8f7050b..c202e02 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -30,7 +30,7 @@
 
   tools {
         maven 'maven_3_latest'
-        jdk 'jdk_1.8_latest'
+        jdk 'jdk_11_latest'
     }
 
 
diff --git a/README.md b/README.md
index f456bf5..b054d0a 100644
--- a/README.md
+++ b/README.md
@@ -103,8 +103,8 @@
 To properly build the StreamPipes core, the following tools should be installed:
 
 ### Prerequisites
-* Java 8 JDK (minimum)
-* Maven (tested with 3.6)
+* Java 11 JDK (minimum)
+* Maven (tested with 3.8)
 * NodeJS + NPM (tested with v12+/ v6+)
 * Docker + Docker-Compose
 
@@ -126,7 +126,7 @@
 
 ### Starting
 
-To start StreamPipes, run ``docker-compose up -d`` from the root directory.
+To start StreamPipes, run ``docker-compose up --build -d`` from the root directory.
 
 You can also use the installer or CLI as described in the ``Installation`` section.
 
@@ -135,7 +135,7 @@
 * **Connect adapters** for a variety of IoT data sources as well as 
 * **Data Processors** and **Data Sinks** as ready-to-use pipeline elements. 
 
-A description of the standard elements can be found in the Github repository [streampipes-extensions](https://www.github.com/apache/incubator-streampipes-extensions).
+A description of the standard elements can be found in [streampipes-extensions](https://github.com/apache/incubator-streampipes/tree/dev/streampipes-extensions).
 
 ## Extending StreamPipes
 
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index ec67a78..dbb6925 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -21,12 +21,72 @@
 
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
-# [Unreleased]
-### New Features
+# [0.70.0]
 
-### Improvements
+## Sub-task
 
-### Bug Fixes
+*   [[STREAMPIPES-535](https://issues.apache.org/jira/browse/STREAMPIPES-535)] - Support JWT signing with private/public key
+
+## Bug
+
+*   [[STREAMPIPES-243](https://issues.apache.org/jira/browse/STREAMPIPES-243)] - Configuration of And Processor is broken
+*   [[STREAMPIPES-255](https://issues.apache.org/jira/browse/STREAMPIPES-255)] - Error when importing AdapterDescriptions with file upload references
+*   [[STREAMPIPES-515](https://issues.apache.org/jira/browse/STREAMPIPES-515)] - Missing mapping in dev compose files for new docker-compose versions
+*   [[STREAMPIPES-521](https://issues.apache.org/jira/browse/STREAMPIPES-521)] - Filter can not be deleted in data explorer
+*   [[STREAMPIPES-524](https://issues.apache.org/jira/browse/STREAMPIPES-524)] - No data is shown in data explorer
+*   [[STREAMPIPES-529](https://issues.apache.org/jira/browse/STREAMPIPES-529)] - Newly created pipelines break dashboard
+*   [[STREAMPIPES-540](https://issues.apache.org/jira/browse/STREAMPIPES-540)] - Data download returns error
+*   [[STREAMPIPES-542](https://issues.apache.org/jira/browse/STREAMPIPES-542)] - Web UI pipelines won't import multiple pipelines
+*   [[STREAMPIPES-543](https://issues.apache.org/jira/browse/STREAMPIPES-543)] - Using UI can't choose a source for the new dashboard
+*   [[STREAMPIPES-547](https://issues.apache.org/jira/browse/STREAMPIPES-547)] - Fix repeating colors for time-series chart
+*   [[STREAMPIPES-548](https://issues.apache.org/jira/browse/STREAMPIPES-548)] - Aggregation settings for data-explorer partially not persisted
+*   [[STREAMPIPES-550](https://issues.apache.org/jira/browse/STREAMPIPES-550)] - Empty property configuration in data-explorer visualization config
+*   [[STREAMPIPES-551](https://issues.apache.org/jira/browse/STREAMPIPES-551)] - Missing naming for (multiple) data sources in visualization config of data-explorer
+*   [[STREAMPIPES-553](https://issues.apache.org/jira/browse/STREAMPIPES-553)] - Lite configuration for k8s does not include message broker
+*   [[STREAMPIPES-554](https://issues.apache.org/jira/browse/STREAMPIPES-554)] - Data-explorer widgets reload when token is renewed
+*   [[STREAMPIPES-564](https://issues.apache.org/jira/browse/STREAMPIPES-564)] - Group by fields don't change in data explorer
+*   [[STREAMPIPES-572](https://issues.apache.org/jira/browse/STREAMPIPES-572)] - Fix automatic lower casing when persisting data in connect
+*   [[STREAMPIPES-578](https://issues.apache.org/jira/browse/STREAMPIPES-578)] - Data Explorer download does not update measurement
+*   [[STREAMPIPES-579](https://issues.apache.org/jira/browse/STREAMPIPES-579)] - Larger live dashboards become unresponsive
+
+## New Feature
+
+*   [[STREAMPIPES-209](https://issues.apache.org/jira/browse/STREAMPIPES-209)] - FileStaticProperty should support filtering for extensions
+*   [[STREAMPIPES-534](https://issues.apache.org/jira/browse/STREAMPIPES-534)] - Support authentication for extensions services
+*   [[STREAMPIPES-539](https://issues.apache.org/jira/browse/STREAMPIPES-539)] - Support full screen data view in data explorer
+*   [[STREAMPIPES-546](https://issues.apache.org/jira/browse/STREAMPIPES-546)] - Support data download of configured query in data explorer
+*   [[STREAMPIPES-549](https://issues.apache.org/jira/browse/STREAMPIPES-549)] - Add extensions service for IIoT-related processors and sinks
+*   [[STREAMPIPES-559](https://issues.apache.org/jira/browse/STREAMPIPES-559)] - Support templates for adapter configurations
+*   [[STREAMPIPES-561](https://issues.apache.org/jira/browse/STREAMPIPES-561)] - Add breadcrumb navigation
+*   [[STREAMPIPES-565](https://issues.apache.org/jira/browse/STREAMPIPES-565)] - Allow to export and import StreamPipes resources
+*   [[STREAMPIPES-569](https://issues.apache.org/jira/browse/STREAMPIPES-569)] - Export data from data lake configuration
+*   [[STREAMPIPES-570](https://issues.apache.org/jira/browse/STREAMPIPES-570)] - Import multiple files at once
+*   [[STREAMPIPES-573](https://issues.apache.org/jira/browse/STREAMPIPES-573)] - Make CSV delimiter selectable in download dialog
+
+## Improvement
+
+*   [[STREAMPIPES-192](https://issues.apache.org/jira/browse/STREAMPIPES-192)] - A user has to enter too many names when using the system
+*   [[STREAMPIPES-223](https://issues.apache.org/jira/browse/STREAMPIPES-223)] - Add connection retry to consul for pipeline elements when starting up
+*   [[STREAMPIPES-228](https://issues.apache.org/jira/browse/STREAMPIPES-228)] - Edit dashboard
+*   [[STREAMPIPES-517](https://issues.apache.org/jira/browse/STREAMPIPES-517)] - Update UI to Angular 13
+*   [[STREAMPIPES-522](https://issues.apache.org/jira/browse/STREAMPIPES-522)] - Deleting adapter instance after previously stopping adapter throws error
+*   [[STREAMPIPES-528](https://issues.apache.org/jira/browse/STREAMPIPES-528)] - Support images in data explorer
+*   [[STREAMPIPES-531](https://issues.apache.org/jira/browse/STREAMPIPES-531)] - Extract shared UI modules to Angular library
+*   [[STREAMPIPES-533](https://issues.apache.org/jira/browse/STREAMPIPES-533)] - Bump Spring dependencies
+*   [[STREAMPIPES-536](https://issues.apache.org/jira/browse/STREAMPIPES-536)] - Escape asterisk in installer/upgrade_versions.sh
+*   [[STREAMPIPES-552](https://issues.apache.org/jira/browse/STREAMPIPES-552)] - Cancel subscriptions in data explorer when config changes
+*   [[STREAMPIPES-556](https://issues.apache.org/jira/browse/STREAMPIPES-556)] - Add silent period to notifications sink
+*   [[STREAMPIPES-557](https://issues.apache.org/jira/browse/STREAMPIPES-557)] - Move notifications icon from iconbar to toolbar
+*   [[STREAMPIPES-558](https://issues.apache.org/jira/browse/STREAMPIPES-558)] - Change navigation of connect module
+*   [[STREAMPIPES-560](https://issues.apache.org/jira/browse/STREAMPIPES-560)] - Add confirm dialog before leaving data explorer widget view
+*   [[STREAMPIPES-575](https://issues.apache.org/jira/browse/STREAMPIPES-575)] - Migrate Math operators from Flink to plain JVM wrapper
+*   [[STREAMPIPES-576](https://issues.apache.org/jira/browse/STREAMPIPES-576)] - Migrate transformation processors from Flink to JVM
+
+## Task
+
+*   [[STREAMPIPES-463](https://issues.apache.org/jira/browse/STREAMPIPES-463)] - Merge StreamPipes repos into a single repo
+*   [[STREAMPIPES-555](https://issues.apache.org/jira/browse/STREAMPIPES-555)] - Remove feedback button from UI
+*   [[STREAMPIPES-581](https://issues.apache.org/jira/browse/STREAMPIPES-581)] - Restructure documentantion
 
 # [0.69.0]
 
diff --git a/archetypes/streampipes-archetype-extensions-jvm/pom.xml b/archetypes/streampipes-archetype-extensions-jvm/pom.xml
index 0bcfc76..f9f1152 100644
--- a/archetypes/streampipes-archetype-extensions-jvm/pom.xml
+++ b/archetypes/streampipes-archetype-extensions-jvm/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
     <artifactId>streampipes-archetype-extensions-jvm</artifactId>
diff --git a/archetypes/streampipes-archetype-extensions-jvm/src/main/resources/archetype-resources/pom.xml b/archetypes/streampipes-archetype-extensions-jvm/src/main/resources/archetype-resources/pom.xml
index 365ab51..5fb4c9c 100644
--- a/archetypes/streampipes-archetype-extensions-jvm/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/streampipes-archetype-extensions-jvm/src/main/resources/archetype-resources/pom.xml
@@ -25,7 +25,7 @@
     <version>${version}</version>
 
     <properties>
-        <sp.version>0.70.0-SNAPSHOT</sp.version>
+        <sp.version>0.71.0-SNAPSHOT</sp.version>
     </properties>
 
     <dependencies>
diff --git a/archetypes/streampipes-archetype-pe-processors-flink/pom.xml b/archetypes/streampipes-archetype-pe-processors-flink/pom.xml
index 5ea6bab..31ff42f 100644
--- a/archetypes/streampipes-archetype-pe-processors-flink/pom.xml
+++ b/archetypes/streampipes-archetype-pe-processors-flink/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
     <artifactId>streampipes-archetype-pe-processors-flink</artifactId>
diff --git a/archetypes/streampipes-archetype-pe-processors-flink/src/main/resources/archetype-resources/pom.xml b/archetypes/streampipes-archetype-pe-processors-flink/src/main/resources/archetype-resources/pom.xml
index e55ddab..2a63d0c 100644
--- a/archetypes/streampipes-archetype-pe-processors-flink/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/streampipes-archetype-pe-processors-flink/src/main/resources/archetype-resources/pom.xml
@@ -25,7 +25,7 @@
     <version>${version}</version>
 
     <properties>
-        <sp.version>0.70.0-SNAPSHOT</sp.version>
+        <sp.version>0.71.0-SNAPSHOT</sp.version>
     </properties>
 
     <dependencies>
diff --git a/archetypes/streampipes-archetype-pe-sinks-flink/pom.xml b/archetypes/streampipes-archetype-pe-sinks-flink/pom.xml
index 6d0837e..0771e8f 100644
--- a/archetypes/streampipes-archetype-pe-sinks-flink/pom.xml
+++ b/archetypes/streampipes-archetype-pe-sinks-flink/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
     <artifactId>streampipes-archetype-pe-sinks-flink</artifactId>
diff --git a/archetypes/streampipes-archetype-pe-sinks-flink/src/main/resources/archetype-resources/pom.xml b/archetypes/streampipes-archetype-pe-sinks-flink/src/main/resources/archetype-resources/pom.xml
index cf27b6f..540d108 100644
--- a/archetypes/streampipes-archetype-pe-sinks-flink/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/streampipes-archetype-pe-sinks-flink/src/main/resources/archetype-resources/pom.xml
@@ -25,7 +25,7 @@
     <version>${version}</version>
 
     <properties>
-        <sp.version>0.70.0-SNAPSHOT</sp.version>
+        <sp.version>0.71.0-SNAPSHOT</sp.version>
     </properties>
 
     <dependencies>
diff --git a/installer/cli/.env b/installer/cli/.env
index 8f4f118..09e1aa2 100644
--- a/installer/cli/.env
+++ b/installer/cli/.env
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 SP_DOCKER_REGISTRY=apachestreampipes
-SP_VERSION=0.70.0-SNAPSHOT
+SP_VERSION=0.71.0-SNAPSHOT
 SP_SUBNET=172.31.0.0/16
 SP_CONSUL_CONTAINER_IP=172.31.0.9
 COMPOSE_PROJECT_NAME=streampipes
diff --git a/installer/cli/README.md b/installer/cli/README.md
index bcfa97a..934a18f 100644
--- a/installer/cli/README.md
+++ b/installer/cli/README.md
@@ -23,7 +23,7 @@
 * new core features for **backend** and **ui**.
 
 <!-- BEGIN do not edit: set via ../upgrade_versions.sh -->
-**Current version:** 0.70.0-SNAPSHOT
+**Current version:** 0.71.0-SNAPSHOT
 <!-- END do not edit -->
 
 ## TL;DR
diff --git a/installer/cli/deploy/standalone/processors-aggregation-flink/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-aggregation-flink/docker-compose.dev.yml
deleted file mode 100644
index dbde6e5..0000000
--- a/installer/cli/deploy/standalone/processors-aggregation-flink/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-aggregation-flink:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-aggregation-flink/docker-compose.yml b/installer/cli/deploy/standalone/processors-aggregation-flink/docker-compose.yml
deleted file mode 100644
index a0d0312..0000000
--- a/installer/cli/deploy/standalone/processors-aggregation-flink/docker-compose.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-aggregation-flink:
-    image: ${SP_DOCKER_REGISTRY}/processors-aggregation-flink:${SP_VERSION}
-    depends_on:
-      - "consul"
-      - "jobmanager"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-enricher-flink/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-enricher-flink/docker-compose.dev.yml
deleted file mode 100644
index 3519024..0000000
--- a/installer/cli/deploy/standalone/processors-enricher-flink/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-enricher-flink:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-enricher-flink/docker-compose.yml b/installer/cli/deploy/standalone/processors-enricher-flink/docker-compose.yml
deleted file mode 100644
index a1cbb64..0000000
--- a/installer/cli/deploy/standalone/processors-enricher-flink/docker-compose.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-enricher-flink:
-    image: ${SP_DOCKER_REGISTRY}/processors-enricher-flink:${SP_VERSION}
-    depends_on:
-      - "consul"
-      - "jobmanager"      
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-enricher-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-enricher-jvm/docker-compose.dev.yml
deleted file mode 100644
index 67ed576..0000000
--- a/installer/cli/deploy/standalone/processors-enricher-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-enricher-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-enricher-jvm/docker-compose.yml b/installer/cli/deploy/standalone/processors-enricher-jvm/docker-compose.yml
deleted file mode 100644
index 1230b85..0000000
--- a/installer/cli/deploy/standalone/processors-enricher-jvm/docker-compose.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-enricher-jvm:
-    image: ${SP_DOCKER_REGISTRY}/processors-enricher-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-filters-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-filters-jvm/docker-compose.dev.yml
deleted file mode 100644
index 178b2b5..0000000
--- a/installer/cli/deploy/standalone/processors-filters-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-filters-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-filters-jvm/docker-compose.yml b/installer/cli/deploy/standalone/processors-filters-jvm/docker-compose.yml
deleted file mode 100644
index e3e2ce0..0000000
--- a/installer/cli/deploy/standalone/processors-filters-jvm/docker-compose.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-filters-jvm:
-    image: ${SP_DOCKER_REGISTRY}/processors-filters-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-filters-siddhi/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-filters-siddhi/docker-compose.dev.yml
deleted file mode 100644
index 207d1ca..0000000
--- a/installer/cli/deploy/standalone/processors-filters-siddhi/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-filters-siddhi:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-filters-siddhi/docker-compose.yml b/installer/cli/deploy/standalone/processors-filters-siddhi/docker-compose.yml
deleted file mode 100644
index 0e647c9..0000000
--- a/installer/cli/deploy/standalone/processors-filters-siddhi/docker-compose.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-filters-siddhi:
-    image: ${SP_DOCKER_REGISTRY}/processors-filters-siddhi:${SP_VERSION}
-    depends_on:
-      - "consul"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-geo-flink/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-geo-flink/docker-compose.dev.yml
deleted file mode 100644
index 0369706..0000000
--- a/installer/cli/deploy/standalone/processors-geo-flink/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-geo-flink:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-geo-flink/docker-compose.yml b/installer/cli/deploy/standalone/processors-geo-flink/docker-compose.yml
deleted file mode 100644
index 8025853..0000000
--- a/installer/cli/deploy/standalone/processors-geo-flink/docker-compose.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-geo-flink:
-    image: ${SP_DOCKER_REGISTRY}/processors-geo-flink:${SP_VERSION}
-    depends_on:
-      - "consul"
-      - "jobmanager"      
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-geo-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-geo-jvm/docker-compose.dev.yml
deleted file mode 100644
index cb8ce93..0000000
--- a/installer/cli/deploy/standalone/processors-geo-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-geo-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-geo-jvm/docker-compose.yml b/installer/cli/deploy/standalone/processors-geo-jvm/docker-compose.yml
deleted file mode 100644
index 9bd02df..0000000
--- a/installer/cli/deploy/standalone/processors-geo-jvm/docker-compose.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-geo-jvm:
-    image: ${SP_DOCKER_REGISTRY}/processors-geo-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-image-processing-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-image-processing-jvm/docker-compose.dev.yml
deleted file mode 100644
index d8130c0..0000000
--- a/installer/cli/deploy/standalone/processors-image-processing-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-image-processing-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-image-processing-jvm/docker-compose.yml b/installer/cli/deploy/standalone/processors-image-processing-jvm/docker-compose.yml
deleted file mode 100644
index 2580b4f..0000000
--- a/installer/cli/deploy/standalone/processors-image-processing-jvm/docker-compose.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-image-processing-jvm:
-    image: ${SP_DOCKER_REGISTRY}/processors-image-processing-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-pattern-detection-flink/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-pattern-detection-flink/docker-compose.dev.yml
deleted file mode 100644
index 541a2f4..0000000
--- a/installer/cli/deploy/standalone/processors-pattern-detection-flink/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-pattern-detection-flink:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-pattern-detection-flink/docker-compose.yml b/installer/cli/deploy/standalone/processors-pattern-detection-flink/docker-compose.yml
deleted file mode 100644
index 7fcc509..0000000
--- a/installer/cli/deploy/standalone/processors-pattern-detection-flink/docker-compose.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-pattern-detection-flink:
-    image: ${SP_DOCKER_REGISTRY}/processors-pattern-detection-flink:${SP_VERSION}
-    depends_on:
-      - "consul"
-      - "jobmanager"      
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-statistics-flink/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-statistics-flink/docker-compose.dev.yml
deleted file mode 100644
index aeda1c1..0000000
--- a/installer/cli/deploy/standalone/processors-statistics-flink/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-statistics-flink:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-statistics-flink/docker-compose.yml b/installer/cli/deploy/standalone/processors-statistics-flink/docker-compose.yml
deleted file mode 100644
index 0d5c24d..0000000
--- a/installer/cli/deploy/standalone/processors-statistics-flink/docker-compose.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-statistics-flink:
-    image: ${SP_DOCKER_REGISTRY}/processors-statistics-flink:${SP_VERSION}
-    depends_on:
-      - "consul"
-      - "jobmanager"      
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-text-mining-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-text-mining-jvm/docker-compose.dev.yml
deleted file mode 100644
index 54bf152..0000000
--- a/installer/cli/deploy/standalone/processors-text-mining-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-text-mining-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-text-mining-jvm/docker-compose.yml b/installer/cli/deploy/standalone/processors-text-mining-jvm/docker-compose.yml
deleted file mode 100644
index 7342d8d..0000000
--- a/installer/cli/deploy/standalone/processors-text-mining-jvm/docker-compose.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-text-mining-jvm:
-    image: ${SP_DOCKER_REGISTRY}/processors-text-mining-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-    volumes:
-      - ./config/models:/data/models
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-transformation-flink/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-transformation-flink/docker-compose.dev.yml
deleted file mode 100644
index b1b8722..0000000
--- a/installer/cli/deploy/standalone/processors-transformation-flink/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-transformation-flink:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-transformation-flink/docker-compose.yml b/installer/cli/deploy/standalone/processors-transformation-flink/docker-compose.yml
deleted file mode 100644
index ad767bc..0000000
--- a/installer/cli/deploy/standalone/processors-transformation-flink/docker-compose.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-transformation-flink:
-    image: ${SP_DOCKER_REGISTRY}/processors-transformation-flink:${SP_VERSION}
-    depends_on:
-      - "consul"
-      - "jobmanager"      
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/processors-transformation-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/processors-transformation-jvm/docker-compose.dev.yml
deleted file mode 100644
index 92ae2be..0000000
--- a/installer/cli/deploy/standalone/processors-transformation-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-transformation-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/processors-transformation-jvm/docker-compose.yml b/installer/cli/deploy/standalone/processors-transformation-jvm/docker-compose.yml
deleted file mode 100644
index f2269dc..0000000
--- a/installer/cli/deploy/standalone/processors-transformation-jvm/docker-compose.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  processors-transformation-jvm:
-    image: ${SP_DOCKER_REGISTRY}/processors-transformation-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-#    ports:
-#      - "8098:8090"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/sinks-brokers-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/sinks-brokers-jvm/docker-compose.dev.yml
deleted file mode 100644
index 5959966..0000000
--- a/installer/cli/deploy/standalone/sinks-brokers-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  sinks-brokers-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/sinks-brokers-jvm/docker-compose.yml b/installer/cli/deploy/standalone/sinks-brokers-jvm/docker-compose.yml
deleted file mode 100644
index 824ef28..0000000
--- a/installer/cli/deploy/standalone/sinks-brokers-jvm/docker-compose.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  sinks-brokers-jvm:
-    image: ${SP_DOCKER_REGISTRY}/sinks-brokers-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/sinks-databases-flink/docker-compose.dev.yml b/installer/cli/deploy/standalone/sinks-databases-flink/docker-compose.dev.yml
deleted file mode 100644
index 41becda..0000000
--- a/installer/cli/deploy/standalone/sinks-databases-flink/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  sinks-databases-flink:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/sinks-databases-flink/docker-compose.yml b/installer/cli/deploy/standalone/sinks-databases-flink/docker-compose.yml
deleted file mode 100644
index 02467dd..0000000
--- a/installer/cli/deploy/standalone/sinks-databases-flink/docker-compose.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  sinks-databases-flink:
-    image: ${SP_DOCKER_REGISTRY}/sinks-databases-flink:${SP_VERSION}
-    depends_on:
-      - "consul"
-      - "jobmanager"      
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/sinks-databases-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/sinks-databases-jvm/docker-compose.dev.yml
deleted file mode 100644
index 8433b08..0000000
--- a/installer/cli/deploy/standalone/sinks-databases-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  sinks-databases-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/sinks-databases-jvm/docker-compose.yml b/installer/cli/deploy/standalone/sinks-databases-jvm/docker-compose.yml
deleted file mode 100644
index ec593aa..0000000
--- a/installer/cli/deploy/standalone/sinks-databases-jvm/docker-compose.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  sinks-databases-jvm:
-    image: ${SP_DOCKER_REGISTRY}/sinks-databases-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/cli/deploy/standalone/sinks-notifications-jvm/docker-compose.dev.yml b/installer/cli/deploy/standalone/sinks-notifications-jvm/docker-compose.dev.yml
deleted file mode 100644
index 25169fe..0000000
--- a/installer/cli/deploy/standalone/sinks-notifications-jvm/docker-compose.dev.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  sinks-notifications-jvm:
-#    ports:
-#      - "8098:8090"
diff --git a/installer/cli/deploy/standalone/sinks-notifications-jvm/docker-compose.yml b/installer/cli/deploy/standalone/sinks-notifications-jvm/docker-compose.yml
deleted file mode 100644
index 5ef9f78..0000000
--- a/installer/cli/deploy/standalone/sinks-notifications-jvm/docker-compose.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-version: "3.4"
-services:
-  sinks-notifications-jvm:
-    image: ${SP_DOCKER_REGISTRY}/sinks-notifications-jvm:${SP_VERSION}
-    depends_on:
-      - "consul"
-    logging:
-      driver: "json-file"
-      options:
-        max-size: "1m"
-        max-file: "1"
-    networks:
-      spnet:
-
-networks:
-  spnet:
-    external: true
diff --git a/installer/compose/.env b/installer/compose/.env
index 1b8ff24..d0e1f62 100644
--- a/installer/compose/.env
+++ b/installer/compose/.env
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-SP_VERSION=0.70.0-SNAPSHOT
+SP_VERSION=0.71.0-SNAPSHOT
 SP_DOCKER_REGISTRY=apachestreampipes
 SP_SUBNET=172.31.0.0/16
 SP_CONSUL_CONTAINER_IP=172.31.0.9
diff --git a/installer/compose/README.md b/installer/compose/README.md
index c22dbed..bd20296 100644
--- a/installer/compose/README.md
+++ b/installer/compose/README.md
@@ -19,7 +19,7 @@
 StreamPipes Compose is a simple collection of user-friendly `docker-compose` files that easily lets gain first-hand experience with Apache StreamPipes.
 
 <!-- BEGIN do not edit: set via ../upgrade_versions.sh -->
-**Current version:** 0.70.0-SNAPSHOT
+**Current version:** 0.71.0-SNAPSHOT
 <!-- END do not edit -->
 
 > **NOTE**: We recommend StreamPipes Compose to only use for initial try-out and testing. If you are a developer and want to develop new pipeline elements or core feature, use the [StreamPipes CLI](../cli).
diff --git a/installer/k8s/Chart.yaml b/installer/k8s/Chart.yaml
index a42d4a8..e88c71a 100644
--- a/installer/k8s/Chart.yaml
+++ b/installer/k8s/Chart.yaml
@@ -14,18 +14,9 @@
 # limitations under the License.
 
 apiVersion: v1
-appVersion: "0.70.0-SNAPSHOT"
+appVersion: "0.71.0-SNAPSHOT"
 description: Self-Service Data Analytics for the Industrial IoT
 name: streampipes-helm-chart
 home: https://streampipes.apache.org
-version: 0.70.0-SNAPSHOT
+version: 0.71.0-SNAPSHOT
 icon: https://avatars1.githubusercontent.com/u/33908576
-maintainers:
-  - name: Dominik Riemer
-    email: riemer@fzi.de
-  - name: Philipp Zehnder
-    email: zehnder@fzi.de
-  - name: Samuel Abt
-    email: abt@fzi.de
-  - name: Patrick Wiener
-    email: wiener@fzi.de
diff --git a/installer/k8s/README.md b/installer/k8s/README.md
index 0449bc6..dff111a 100644
--- a/installer/k8s/README.md
+++ b/installer/k8s/README.md
@@ -19,7 +19,7 @@
 StreamPipes k8s is a helm chart to deploy StreamPipes on Kubernetes.
 
 <!-- BEGIN do not edit: set via ../upgrade_versions.sh -->
-**Current version:** 0.70.0-SNAPSHOT
+**Current version:** 0.71.0-SNAPSHOT
 <!-- END do not edit -->
 
 We provide two helm chart templates to get you going:
diff --git a/installer/k8s/templates/core/backend-deployment.yaml b/installer/k8s/templates/core/backend-deployment.yaml
index a2a1b63..592c569 100644
--- a/installer/k8s/templates/core/backend-deployment.yaml
+++ b/installer/k8s/templates/core/backend-deployment.yaml
@@ -44,7 +44,7 @@
           imagePullPolicy: {{ .Values.pullPolicy }}
           env:
             - name: SP_PRIORITIZED_PROTOCOL
-              {{ if (eq .Values.deployment "lite") }}
+              {{ if (eq .Values.preferredBroker "mqtt") }}
               value: "mqtt"
               {{ else }}
               value: "kafka"
diff --git a/installer/k8s/templates/extensions/connect-adapters/connect-adapters-deployment.yaml b/installer/k8s/templates/extensions/connect-adapters/connect-adapters-deployment.yaml
deleted file mode 100644
index 1dc5526..0000000
--- a/installer/k8s/templates/extensions/connect-adapters/connect-adapters-deployment.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: connect-adapters
-spec:
-  selector:
-    matchLabels:
-      app: connect-adapters
-  replicas: 1
-  template:
-    metadata:
-      labels:
-        app: connect-adapters
-    spec:         
-      containers:
-        - name: connect-adapters
-          image: {{ .Values.streampipes.registry }}/connect-adapters:{{ .Values.streampipes.version }}
-          imagePullPolicy: {{ .Values.pullPolicy }}
-          ports:
-            - containerPort: 8090
diff --git a/installer/k8s/templates/extensions/connect-adapters/connect-adapters-iiot-deployment.yaml b/installer/k8s/templates/extensions/connect-adapters/connect-adapters-iiot-deployment.yaml
deleted file mode 100644
index a67ff5e..0000000
--- a/installer/k8s/templates/extensions/connect-adapters/connect-adapters-iiot-deployment.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: connect-adapters-iiot
-spec:
-  selector:
-    matchLabels:
-      app: connect-adapters-iiot
-  replicas: 1
-  template:
-    metadata:
-      labels:
-        app: connect-adapters-iiot
-    spec:         
-      containers:
-        - name: connect-adapters-iiot
-          image: {{ .Values.streampipes.registry }}/connect-adapters-iiot:{{ .Values.streampipes.version }}
-          imagePullPolicy: {{ .Values.pullPolicy }}
-          ports:
-            - containerPort: 8090
diff --git a/installer/k8s/templates/extensions/connect-adapters/connect-adapters-iiot-service.yaml b/installer/k8s/templates/extensions/connect-adapters/connect-adapters-iiot-service.yaml
deleted file mode 100644
index d4ec559..0000000
--- a/installer/k8s/templates/extensions/connect-adapters/connect-adapters-iiot-service.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-apiVersion: v1
-kind: Service
-metadata:
-  name: connect-adapters-iiot
-spec:
-  selector:
-    app: connect-adapters-iiot
-  ports:
-    - name: main
-      protocol: TCP
-      port: 8090
-      targetPort: 8002
diff --git a/installer/k8s/templates/extensions/connect-adapters/connect-adapters-service.yaml b/installer/k8s/templates/extensions/connect-adapters/connect-adapters-service.yaml
deleted file mode 100644
index 213aef3..0000000
--- a/installer/k8s/templates/extensions/connect-adapters/connect-adapters-service.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-apiVersion: v1
-kind: Service
-metadata:
-  name: connect-adapters
-spec:
-  selector:
-    app: connect-adapters
-  ports:
-    - name: main
-      protocol: TCP
-      port: 8090
-      targetPort: 8001
diff --git a/installer/k8s/templates/extensions/pipeline-elements/pipeline-elements-all-jvm-deployment.yaml b/installer/k8s/templates/extensions/pipeline-elements/extensions-all-jvm-deployment.yaml
similarity index 77%
rename from installer/k8s/templates/extensions/pipeline-elements/pipeline-elements-all-jvm-deployment.yaml
rename to installer/k8s/templates/extensions/pipeline-elements/extensions-all-jvm-deployment.yaml
index 6508e37..fb1cf7f 100644
--- a/installer/k8s/templates/extensions/pipeline-elements/pipeline-elements-all-jvm-deployment.yaml
+++ b/installer/k8s/templates/extensions/pipeline-elements/extensions-all-jvm-deployment.yaml
@@ -16,27 +16,27 @@
 apiVersion: apps/v1
 kind: Deployment
 metadata:
-  name: pipeline-elements-all-jvm
+  name: extensions-all-jvm
 spec:
   selector:
     matchLabels:
-      app: pipeline-elements-all-jvm
+      app: extensions-all-jvm
   replicas: 1
   template:
     metadata:
       labels:
-        app: pipeline-elements-all-jvm
+        app: extensions-all-jvm
     spec:
       volumes:
         - name: files-pv
           persistentVolumeClaim:
-            claimName: files-pvc          
+            claimName: files-pvc
       containers:
-        - name: pipeline-elements-all-jvm
-          image: {{ .Values.streampipes.registry }}/pipeline-elements-all-jvm:{{ .Values.streampipes.version }}
+        - name: extensions-all-jvm
+          image: {{ .Values.streampipes.registry }}/extensions-all-jvm:{{ .Values.streampipes.version }}
           imagePullPolicy: {{ .Values.pullPolicy }}
           ports:
             - containerPort: 8090
           volumeMounts:
             - mountPath: "/spImages"
-              name: files-pv          
+              name: files-pv
diff --git a/installer/k8s/templates/extensions/pipeline-elements/pipeline-elements-all-jvm-service.yaml b/installer/k8s/templates/extensions/pipeline-elements/extensions-all-jvm-service.yaml
similarity index 89%
rename from installer/k8s/templates/extensions/pipeline-elements/pipeline-elements-all-jvm-service.yaml
rename to installer/k8s/templates/extensions/pipeline-elements/extensions-all-jvm-service.yaml
index 1b1b01c..8a3a36a 100644
--- a/installer/k8s/templates/extensions/pipeline-elements/pipeline-elements-all-jvm-service.yaml
+++ b/installer/k8s/templates/extensions/pipeline-elements/extensions-all-jvm-service.yaml
@@ -16,14 +16,14 @@
 apiVersion: v1
 kind: Service
 metadata:
-  name: pipeline-elements-all-jvm
+  name: extensions-all-jvm
   labels:
-    name: pipeline-elements-all-jvm
+    name: extensions-all-jvm
 spec:
   selector:
-    app: pipeline-elements-all-jvm
+    app: extensions-all-jvm
   ports:
     - name: main
       protocol: TCP
       port: 8090
-      targetPort: 8090
\ No newline at end of file
+      targetPort: 8090
diff --git a/installer/k8s/templates/extensions/pipeline-elements/files-pvc.yaml b/installer/k8s/templates/extensions/pipeline-elements/files-pvc.yaml
index bd6a088..ee0fb64 100644
--- a/installer/k8s/templates/extensions/pipeline-elements/files-pvc.yaml
+++ b/installer/k8s/templates/extensions/pipeline-elements/files-pvc.yaml
@@ -31,7 +31,7 @@
 kind: PersistentVolumeClaim
 metadata:
   labels:
-    app: pipeline-elements-all-jvm
+    app: extensions-all-jvm
   name: files-pvc
 spec:
   storageClassName: local-storage-files
@@ -39,4 +39,4 @@
     - {{ .Values.persistentVolumeAccessModes }}
   resources:
     requests:
-      storage: 250Mi
\ No newline at end of file
+      storage: 250Mi
diff --git a/installer/k8s/templates/external/kafka/kafka-deployment.yaml b/installer/k8s/templates/external/kafka/kafka-deployment.yaml
index eb844d7..4d45116 100644
--- a/installer/k8s/templates/external/kafka/kafka-deployment.yaml
+++ b/installer/k8s/templates/external/kafka/kafka-deployment.yaml
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-{{- if (eq .Values.deployment "full") }}
 apiVersion: apps/v1
 kind: Deployment
 metadata:
@@ -66,4 +65,3 @@
               value: "5000012"
             - name: KAFKA_REPLICA_FETCH_MAX_BYTES
               value: "10000000"
-{{- end }}
\ No newline at end of file
diff --git a/installer/k8s/templates/external/kafka/kafka-pvc.yaml b/installer/k8s/templates/external/kafka/kafka-pvc.yaml
index 3bda2e2..894ae6c 100644
--- a/installer/k8s/templates/external/kafka/kafka-pvc.yaml
+++ b/installer/k8s/templates/external/kafka/kafka-pvc.yaml
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-{{- if (eq .Values.deployment "full") }}
 apiVersion: v1
 kind: PersistentVolume
 metadata:
@@ -41,4 +40,3 @@
   resources:
     requests:
       storage: 50M
-{{- end }}
\ No newline at end of file
diff --git a/installer/k8s/templates/external/kafka/kafka-service.yaml b/installer/k8s/templates/external/kafka/kafka-service.yaml
index 1b75c43..1e1c265 100644
--- a/installer/k8s/templates/external/kafka/kafka-service.yaml
+++ b/installer/k8s/templates/external/kafka/kafka-service.yaml
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-{{- if (eq .Values.deployment "full") }}
 apiVersion: v1
 kind: Service
 metadata:
@@ -27,4 +26,3 @@
     - name: main
       protocol: TCP
       port: 9092
-{{- end }}
\ No newline at end of file
diff --git a/installer/k8s/templates/external/zookeeper/zookeeper-deployment.yaml b/installer/k8s/templates/external/zookeeper/zookeeper-deployment.yaml
index 6debfc6..756ae4e 100644
--- a/installer/k8s/templates/external/zookeeper/zookeeper-deployment.yaml
+++ b/installer/k8s/templates/external/zookeeper/zookeeper-deployment.yaml
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-{{- if (eq .Values.deployment "full") }}
 apiVersion: apps/v1
 kind: Deployment
 metadata:
@@ -43,4 +42,3 @@
           volumeMounts:
             - mountPath: "/opt/zookeeper-{{ .Values.external.zookeeperVersion }}/data"
               name: zookeeper-pv
-{{- end }}
\ No newline at end of file
diff --git a/installer/k8s/templates/external/zookeeper/zookeeper-pvc.yaml b/installer/k8s/templates/external/zookeeper/zookeeper-pvc.yaml
index cbd9b45..741bc9b 100644
--- a/installer/k8s/templates/external/zookeeper/zookeeper-pvc.yaml
+++ b/installer/k8s/templates/external/zookeeper/zookeeper-pvc.yaml
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-{{- if (eq .Values.deployment "full") }}
 apiVersion: v1
 kind: PersistentVolume
 metadata:
@@ -41,4 +40,3 @@
   resources:
     requests:
       storage: 20M
-{{- end }}
\ No newline at end of file
diff --git a/installer/k8s/templates/external/zookeeper/zookeeper-service.yaml b/installer/k8s/templates/external/zookeeper/zookeeper-service.yaml
index cb10589..d65bdb9 100644
--- a/installer/k8s/templates/external/zookeeper/zookeeper-service.yaml
+++ b/installer/k8s/templates/external/zookeeper/zookeeper-service.yaml
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-{{- if (eq .Values.deployment "full") }}
 apiVersion: v1
 kind: Service
 metadata:
@@ -26,4 +25,3 @@
       protocol: TCP
       port: 2181
       targetPort: 2181
-{{- end }}
\ No newline at end of file
diff --git a/installer/k8s/values.yaml b/installer/k8s/values.yaml
index 0f662c7..cbbfd9b 100644
--- a/installer/k8s/values.yaml
+++ b/installer/k8s/values.yaml
@@ -15,12 +15,13 @@
 
 # lite or full (default: lite)
 deployment: lite
+preferredBroker: "kafka"
 pullPolicy: "IfNotPresent"
-persistentVolumeReclaimPolicy: "Retain"
+persistentVolumeReclaimPolicy: "Delete"
 persistentVolumeAccessModes: "ReadWriteOnce"
 
 streampipes:
-  version: "0.70.0-SNAPSHOT"
+  version: "0.71.0-SNAPSHOT"
   registry: "apachestreampipes"
 
 external:
diff --git a/installer/upgrade_versions.sh b/installer/upgrade_versions.sh
index 1c98145..fef8845 100755
--- a/installer/upgrade_versions.sh
+++ b/installer/upgrade_versions.sh
@@ -47,7 +47,7 @@
 
         for opt in "${options[@]}"
         do
-          sed -i 's/**Current version:** .*/**Current version:** '$NEW_VERSION'/g' ./$opt/README.md
+          sed -i 's/\*\*Current version:\*\* .*/\*\*Current version:\*\* '$NEW_VERSION'/g' ./$opt/README.md
         done
         ;;
   esac
diff --git a/pom.xml b/pom.xml
index e35c0f4..30e1d65 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,8 +17,7 @@
 ~
 -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 
 <parent>
@@ -29,7 +28,7 @@
 
 <groupId>org.apache.streampipes</groupId>
 <artifactId>streampipes-parent</artifactId>
-<version>0.70.0-SNAPSHOT</version>
+<version>0.71.0-SNAPSHOT</version>
 <packaging>pom</packaging>
 
 <properties>
@@ -83,7 +82,7 @@
 	<jboss-logging-processor.version>2.2.1.Final</jboss-logging-processor.version>
 	<jersey.version>2.35</jersey.version>
 	<jetbrains-annotations.version>16.0.2</jetbrains-annotations.version>
-	<jetty.version>9.4.44.v20210927</jetty.version>
+	<jetty.version>10.0.10</jetty.version>
 	<jgrapht.version>1.3.1</jgrapht.version>
 	<jjwt.version>0.11.2</jjwt.version>
 	<json-path.version>3.1.0</json-path.version>
@@ -109,14 +108,15 @@
 	<slf4j.version>1.7.30</slf4j.version>
 	<snakeyaml.version>1.26</snakeyaml.version>
 	<snappy-java.version>1.1.7.7</snappy-java.version>
-	<spring.version>5.3.19</spring.version>
+	<spring.version>5.3.20</spring.version>
 	<spring-boot.version>2.6.7</spring-boot.version>
-	<spring-security.version>5.6.3</spring-security.version>
+	<spring-security.version>5.6.4</spring-security.version>
 	<swagger.version>2.1.12</swagger.version>
 	<type-parser.version>0.6.0</type-parser.version>
 	<underscore.version>1.47</underscore.version>
 	<wildfly-common.version>1.5.4.Final</wildfly-common.version>
 	<hawtbuf.version>1.11</hawtbuf.version>
+	<netty-tc-native.version>2.0.52.Final</netty-tc-native.version>
 
 	<!-- Test dependencies -->
 	<junit.version>4.13.2</junit.version>
@@ -222,7 +222,7 @@
 				<dependency>
 					<groupId>com.google.code.gson</groupId>
 					<artifactId>gson</artifactId>
-					<version>2.8.8</version>
+					<version>2.8.9</version>
 				</dependency>
 				<dependency>
 					<groupId>com.google.guava</groupId>
@@ -840,6 +840,11 @@
 					<artifactId>siddhi-query-compiler</artifactId>
 					<version>${siddhi.version}</version>
 				</dependency>
+				<dependency>
+					<groupId>io.netty</groupId>
+					<artifactId>netty-tcnative-classes</artifactId>
+					<version>${netty-tc-native.version}</version>
+				</dependency>
 
 				<!-- Test dependencies -->
 				<dependency>
@@ -956,7 +961,9 @@
 			<module>streampipes-mail</module>
 			<module>streampipes-resource-management</module>
 			<module>streampipes-sdk-bundle</module>
-		</modules>
+            <module>streampipes-data-explorer-commons</module>
+            <module>streampipes-data-export</module>
+        </modules>
 
 		<profiles>
 			<profile>
@@ -1153,7 +1160,7 @@
 						</goals>
 						<configuration>
 							<rules>
-								<dependencyConvergence/>
+								<dependencyConvergence />
 							</rules>
 						</configuration>
 					</execution>
@@ -1272,6 +1279,9 @@
 						<!-- Exclude some UI files which we need to check in more detail -->
 						<exclude>ui/src/assets/img/svg/**</exclude>
 
+						<!-- Exclude .angular folder -->
+						<exclude>ui/.angular/**</exclude>
+
 						<!-- Exclude disclaimer and notice files -->
 						<exclude>DISCLAIMER</exclude>
 						<exclude>NOTICE-binary</exclude>
@@ -1381,7 +1391,7 @@
 		<developerConnection>scm:git:ssh://git@github.com/apache/incubator-streampipes.git</developerConnection>
 		<connection>scm:git:ssh://git@github.com/apache/incubator-streampipes.git</connection>
 		<url>https://github.com/apache/incubator-streampipes</url>
-		<tag>HEAD</tag>
+		<tag>rel/0.70.0</tag>
 	</scm>
 
 	<issueManagement>
diff --git a/streampipes-backend/pom.xml b/streampipes-backend/pom.xml
index 30797b6..a0c5280 100644
--- a/streampipes-backend/pom.xml
+++ b/streampipes-backend/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>streampipes-backend</artifactId>
@@ -33,7 +33,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-base</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.springframework.boot</groupId>
@@ -44,27 +44,27 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-kafka</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-rest</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect-container-master</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-platform-services</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <!-- External dependencies -->
         <dependency>
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
index 6b0fe4f..260fc6f 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
@@ -17,6 +17,7 @@
  */
 package org.apache.streampipes.backend;
 
+import org.apache.streampipes.backend.migrations.MigrationsHandler;
 import org.apache.streampipes.config.backend.BackendConfig;
 import org.apache.streampipes.manager.health.PipelineHealthCheck;
 import org.apache.streampipes.manager.operations.Operations;
@@ -27,6 +28,7 @@
 import org.apache.streampipes.service.base.BaseNetworkingConfig;
 import org.apache.streampipes.service.base.StreamPipesServiceBase;
 import org.apache.streampipes.storage.api.IPipelineStorage;
+import org.apache.streampipes.storage.couchdb.utils.CouchDbViewGenerator;
 import org.apache.streampipes.storage.management.StorageDispatcher;
 import org.apache.streampipes.svcdiscovery.api.model.DefaultSpServiceGroups;
 import org.apache.streampipes.svcdiscovery.api.model.DefaultSpServiceTags;
@@ -96,11 +98,14 @@
     this.executorService = Executors.newSingleThreadScheduledExecutor();
     this.healthCheckExecutorService = Executors.newSingleThreadScheduledExecutor();
 
+    new StreamPipesEnvChecker().updateEnvironmentVariables();
+    new CouchDbViewGenerator().createGenericDatabaseIfNotExists();
+
     if (!isConfigured()) {
       doInitialSetup();
     }
 
-    new StreamPipesEnvChecker().updateEnvironmentVariables();
+    new MigrationsHandler().performMigrations();
 
     executorService.schedule(this::startAllPreviouslyStoppedPipelines, 5, TimeUnit.SECONDS);
     LOG.info("Pipeline health check will run every {} seconds", HEALTH_CHECK_INTERVAL);
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesResourceConfig.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesResourceConfig.java
index 80dd28b..96ccf69 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesResourceConfig.java
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesResourceConfig.java
@@ -19,10 +19,7 @@
 package org.apache.streampipes.backend;
 
 import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
-import org.apache.streampipes.ps.DataLakeImageResource;
-import org.apache.streampipes.ps.DataLakeResourceV3;
-import org.apache.streampipes.ps.DataLakeResourceV4;
-import org.apache.streampipes.ps.PipelineElementTemplateResource;
+import org.apache.streampipes.ps.*;
 import org.apache.streampipes.rest.impl.*;
 import org.apache.streampipes.rest.impl.admin.*;
 import org.apache.streampipes.rest.impl.connect.*;
@@ -30,7 +27,6 @@
 import org.apache.streampipes.rest.impl.dashboard.DashboardWidget;
 import org.apache.streampipes.rest.impl.dashboard.VisualizablePipelineResource;
 import org.apache.streampipes.rest.impl.datalake.DataLakeDashboardResource;
-import org.apache.streampipes.rest.impl.datalake.DataLakeMeasureResourceV3;
 import org.apache.streampipes.rest.impl.datalake.DataLakeWidgetResource;
 import org.apache.streampipes.rest.impl.datalake.PersistedDataStreamResource;
 import org.apache.streampipes.rest.impl.nouser.PipelineElementImportNoUser;
@@ -55,20 +51,25 @@
         register(AccountActivationResource.class);
         register(Authentication.class);
         register(AssetDashboardResource.class);
+        register(AssetManagementResource.class);
         register(AutoComplete.class);
         register(CategoryResource.class);
         register(ConsulConfig.class);
         register(ContainerProvidedOptions.class);
         register(DashboardWidget.class);
         register(Dashboard.class);
+        register(DataExportResource.class);
+        register(DataImportResource.class);
         register(DataLakeImageResource.class);
         register(DataLakeResourceV3.class);
         register(DataLakeMeasureResourceV3.class);
+        register(DataLakeMeasureResourceV4.class);
         register(DataStream.class);
         register(EmailConfigurationResource.class);
         register(EmailResource.class);
         register(ExtensionsServiceEndpointResource.class);
         register(GeneralConfigurationResource.class);
+        register(GenericStorageResource.class);
         register(LabelResource.class);
         register(MeasurementUnitResource.class);
         register(Notification.class);
@@ -102,7 +103,6 @@
         register(DataLakeDashboardResource.class);
         register(DataLakeWidgetResource.class);
         register(DataLakeResourceV3.class);
-        register(DataLakeMeasureResourceV3.class);
         register(PipelineElementFile.class);
         register(DashboardWidget.class);
         register(Dashboard.class);
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
new file mode 100644
index 0000000..5b26d79
--- /dev/null
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.backend.migrations;
+
+import org.apache.streampipes.backend.migrations.v070.CreateAssetLinkTypeMigration;
+import org.apache.streampipes.backend.migrations.v070.CreateDefaultAssetMigration;
+import org.apache.streampipes.backend.migrations.v070.CreateFileAssetTypeMigration;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class AvailableMigrations {
+
+  public List<Migration> getAvailableMigrations() {
+    return Arrays.asList(
+      new CreateAssetLinkTypeMigration(),
+      new CreateDefaultAssetMigration(),
+      new CreateFileAssetTypeMigration()
+    );
+  }
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/Migration.java
similarity index 78%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/Migration.java
index 58ba04b..0cabbfa 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/Migration.java
@@ -16,3 +16,16 @@
  *
  */
 
+
+package org.apache.streampipes.backend.migrations;
+
+import java.io.IOException;
+
+public interface Migration {
+
+  boolean shouldExecute();
+
+  void executeMigration() throws IOException;
+
+  String getDescription();
+}
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/MigrationsHandler.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/MigrationsHandler.java
new file mode 100644
index 0000000..72ea592
--- /dev/null
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/MigrationsHandler.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.backend.migrations;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+public class MigrationsHandler {
+
+  private static final Logger LOG = LoggerFactory.getLogger(MigrationsHandler.class);
+
+  public void performMigrations() {
+    LOG.info("Checking for required migrations...");
+    var availableMigrations = new AvailableMigrations().getAvailableMigrations();
+
+    availableMigrations.forEach(migration -> {
+      if (migration.shouldExecute()) {
+        LOG.info("Performing migration: {}", migration.getDescription());
+        try {
+          migration.executeMigration();
+        } catch (IOException e) {
+          LOG.error("An error has occurred while executing migration '{}'", migration.getDescription(), e);
+        }
+      }
+    });
+
+    LOG.info("All migrations completed.");
+  }
+}
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateAssetLinkTypeMigration.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateAssetLinkTypeMigration.java
new file mode 100644
index 0000000..27463d9
--- /dev/null
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateAssetLinkTypeMigration.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.backend.migrations.v070;
+
+import org.apache.streampipes.backend.migrations.Migration;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+import org.apache.streampipes.manager.setup.tasks.CreateAssetLinkTypeTask;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+
+public class CreateAssetLinkTypeMigration implements Migration {
+
+  @Override
+  public boolean shouldExecute() {
+    try {
+      return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().findAll(GenericDocTypes.DOC_ASSET_LINK_TYPE).size() == 0;
+    } catch (IOException e) {
+      return true;
+    }
+  }
+
+  @Override
+  public void executeMigration() {
+    new CreateAssetLinkTypeTask().execute();
+  }
+
+  @Override
+  public String getDescription() {
+    return "Populating database with default asset links";
+  }
+}
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateDefaultAssetMigration.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateDefaultAssetMigration.java
new file mode 100644
index 0000000..7cf10d5
--- /dev/null
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateDefaultAssetMigration.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.backend.migrations.v070;
+
+import org.apache.streampipes.backend.migrations.Migration;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+import org.apache.streampipes.manager.setup.tasks.CreateDefaultAssetTask;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+
+public class CreateDefaultAssetMigration implements Migration {
+
+  @Override
+  public boolean shouldExecute() {
+    try {
+      return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().findOne(GenericDocTypes.DEFAULT_ASSET_DOC_ID) == null;
+    } catch (IOException e) {
+      return true;
+    }
+  }
+
+  @Override
+  public void executeMigration() {
+    new CreateDefaultAssetTask().execute();
+  }
+
+  @Override
+  public String getDescription() {
+    return "Creating a default asset representation";
+  }
+}
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateFileAssetTypeMigration.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateFileAssetTypeMigration.java
new file mode 100644
index 0000000..56d837b
--- /dev/null
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateFileAssetTypeMigration.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.backend.migrations.v070;
+
+import org.apache.streampipes.backend.migrations.Migration;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+import org.apache.streampipes.commons.random.UUIDGenerator;
+import org.apache.streampipes.model.assets.AssetLinkType;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+import java.util.List;
+
+public class CreateFileAssetTypeMigration implements Migration {
+
+  @Override
+  public boolean shouldExecute() {
+    try {
+      return StorageDispatcher
+        .INSTANCE
+        .getNoSqlStore()
+        .getGenericStorage()
+        .findAll(GenericDocTypes.DOC_ASSET_LINK_TYPE)
+        .stream()
+        .noneMatch(al -> al.get("linkType").equals("file"));
+    } catch (IOException e) {
+      return true;
+    }
+  }
+
+  @Override
+  public void executeMigration() throws IOException {
+    var fileAsset = new AssetLinkType("file", "File", "var(--color-file)", "draft", "file", List.of(), false);
+    fileAsset.setId(UUIDGenerator.generateUuid());
+    StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().create(fileAsset, AssetLinkType.class);
+
+  }
+
+  @Override
+  public String getDescription() {
+    return "Create asset type 'File'";
+  }
+}
diff --git a/streampipes-client/pom.xml b/streampipes-client/pom.xml
index be30324..b654f3b 100644
--- a/streampipes-client/pom.xml
+++ b/streampipes-client/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,42 +32,42 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-cbor</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-fst</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-kafka</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-security-jwt</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-serializers-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- 3rd party Dependencies -->
diff --git a/streampipes-client/src/main/java/org/apache/streampipes/client/http/HttpRequest.java b/streampipes-client/src/main/java/org/apache/streampipes/client/http/HttpRequest.java
index 5c11455..cd5d178 100644
--- a/streampipes-client/src/main/java/org/apache/streampipes/client/http/HttpRequest.java
+++ b/streampipes-client/src/main/java/org/apache/streampipes/client/http/HttpRequest.java
@@ -74,11 +74,11 @@
     return headers.toArray(new Header[0]);
   }
 
-  protected String makeUrl() {
+  protected String makeUrl() throws SpRuntimeException {
     return makeUrl(true);
   }
 
-  protected String makeUrl(boolean includePath) {
+  protected String makeUrl(boolean includePath) throws SpRuntimeException {
     String baseUrl = clientConfig.getConnectionConfig().getBaseUrl();
     if (includePath) {
       baseUrl = baseUrl + "/" + apiPath.toString();
@@ -87,7 +87,7 @@
     return baseUrl;
   }
 
-  public DT executeRequest() throws SpRuntimeException {
+  public DT executeRequest() {
     Request request = makeRequest(serializer);
     try {
       HttpResponse response = request.execute().returnResponse();
@@ -101,10 +101,8 @@
           throw new SpRuntimeException(status.getStatusCode() + " - " + status.getReasonPhrase());
         }
       }
-    } catch (NoHttpResponseException e) {
-      throw new SpRuntimeException("Could not connect to the StreamPipes API - please check that StreamPipes is available at " + makeUrl(false));
-    } catch (IOException e) {
-      throw new SpRuntimeException(e.getMessage());
+    } catch (IOException | SpRuntimeException e) {
+      throw new SpRuntimeException("Could not connect to the StreamPipes API - please check that StreamPipes is available");
     }
   }
 
diff --git a/streampipes-commons/pom.xml b/streampipes-commons/pom.xml
index ab46b5f..8a9e80b 100644
--- a/streampipes-commons/pom.xml
+++ b/streampipes-commons/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>streampipes-commons</artifactId>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GenericDocTypes.java
similarity index 72%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GenericDocTypes.java
index 58ba04b..813f06b 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GenericDocTypes.java
@@ -16,3 +16,13 @@
  *
  */
 
+package org.apache.streampipes.commons.constants;
+
+public class GenericDocTypes {
+
+  public static final String DOC_ASSET_MANGEMENT = "asset-management";
+  public static final String DOC_ASSET_LINK_TYPE = "asset-link-type";
+
+
+  public static final String DEFAULT_ASSET_DOC_ID = "default-asset";
+}
diff --git a/streampipes-commons/src/main/java/org/apache/streampipes/commons/exceptions/SpConfigurationException.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/exceptions/SpConfigurationException.java
new file mode 100644
index 0000000..321330b
--- /dev/null
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/exceptions/SpConfigurationException.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.commons.exceptions;
+
+public class SpConfigurationException extends Exception {
+
+  /**
+   * Creates a new Exception with the given message and null as the cause.
+   *
+   * @param message The exception message
+   */
+  public SpConfigurationException(String message) {
+    super(message);
+  }
+
+  /**
+   * Creates a new exception with a null message and the given cause.
+   *
+   * @param cause The exception that caused this exception
+   */
+  public SpConfigurationException(Throwable cause) {
+    super(cause);
+  }
+
+  /**
+   * Creates a new exception with the given message and cause
+   *
+   * @param message The exception message
+   * @param cause The exception that caused this exception
+   */
+  public SpConfigurationException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git a/streampipes-commons/src/main/java/org/apache/streampipes/commons/networking/Networking.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/networking/Networking.java
index 489a557..bb98349 100644
--- a/streampipes-commons/src/main/java/org/apache/streampipes/commons/networking/Networking.java
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/networking/Networking.java
@@ -21,13 +21,15 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
+import java.io.IOException;
+import java.net.*;
 
 public class Networking {
 
   private static final Logger LOG = LoggerFactory.getLogger(Networking.class);
 
+  private static final String DEFAULT_LOCALHOST_IP = "127.0.0.1";
+
   public static String getHostname() throws UnknownHostException {
     String selectedAddress;
     if (Envs.SP_HOST.exists()) {
@@ -35,12 +37,43 @@
       LOG.info("Using IP from provided environment variable {}: {}", Envs.SP_HOST, selectedAddress);
     } else {
       selectedAddress = InetAddress.getLocalHost().getHostAddress();
+
+      // this condition is only used as a workaround when the IP address was not derived correctly
+      // when this also does not work, you must set the environment variable SP_HOST manually
+      if (selectedAddress.equals(DEFAULT_LOCALHOST_IP)) {
+        selectedAddress = getIpAddressForOsx();
+      }
+
       LOG.info("Using auto-discovered IP: {}", selectedAddress);
     }
 
     return selectedAddress;
   }
 
+  /**
+   * this method is a workaround for developers using osx
+   * in OSX InetAddress.getLocalHost().getHostAddress() always returns 127.0.0.1
+   * as a workaround developers must manually set the SP_HOST environment variable with the actual ip
+   * with this method the IP is set automatically
+   *
+   * @return IP
+   */
+  private static String getIpAddressForOsx() {
+
+    Socket socket = new Socket();
+    String result = DEFAULT_LOCALHOST_IP;
+    try {
+      socket.connect(new InetSocketAddress("streampipes.apache.org", 80));
+      result = socket.getLocalAddress().getHostAddress();
+      socket.close();
+    } catch (IOException e) {
+      LOG.error(e.getMessage());
+      LOG.error("IP address was not set automatically. Use the environment variable SP_HOST to set it manually.");
+    }
+
+    return result;
+  }
+
   public static Integer getPort(Integer defaultPort) {
     Integer selectedPort;
     if (Envs.SP_PORT.exists()) {
diff --git a/streampipes-commons/src/main/java/org/apache/streampipes/commons/zip/ZipFileExtractor.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/zip/ZipFileExtractor.java
index 5ada0f4..12e5af6 100644
--- a/streampipes-commons/src/main/java/org/apache/streampipes/commons/zip/ZipFileExtractor.java
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/zip/ZipFileExtractor.java
@@ -17,10 +17,9 @@
  */
 package org.apache.streampipes.commons.zip;
 
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
@@ -32,6 +31,32 @@
     this.zipInputStream = zipInputStream;
   }
 
+  // TODO used by export feature - extend this to support binaries
+  public Map<String, byte[]> extractZipToMap() throws IOException {
+    byte[] buffer = new byte[1024];
+    Map<String, byte[]> entries = new HashMap<>();
+    ZipInputStream zis = new ZipInputStream(zipInputStream);
+    ZipEntry zipEntry = zis.getNextEntry();
+    while (zipEntry != null) {
+      ByteArrayOutputStream fos = new ByteArrayOutputStream();
+      int len;
+      while ((len = zis.read(buffer)) > 0) {
+        fos.write(buffer, 0, len);
+      }
+      entries.put(sanitizeName(zipEntry.getName()), fos.toByteArray());
+      fos.close();
+      zipEntry = zis.getNextEntry();
+    }
+    zis.closeEntry();
+    zis.close();
+
+    return entries;
+  }
+
+  private String sanitizeName(String name) {
+    return name.split("\\.")[0];
+  }
+
   public void extractZipToFile(String targetFolder) throws IOException {
     File destDir = new File(targetFolder);
     if (!destDir.exists()) {
diff --git a/streampipes-config/pom.xml b/streampipes-config/pom.xml
index 48c4a4f..5e953bb 100644
--- a/streampipes-config/pom.xml
+++ b/streampipes-config/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,17 +32,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-serializers-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-vocabulary</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-discovery</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-connect-api/pom.xml b/streampipes-connect-api/pom.xml
index 75f5c9b..a7bbbd9 100644
--- a/streampipes-connect-api/pom.xml
+++ b/streampipes-connect-api/pom.xml
@@ -17,13 +17,11 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -33,7 +31,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
     <properties>
diff --git a/streampipes-connect-api/src/main/java/org/apache/streampipes/connect/api/IParser.java b/streampipes-connect-api/src/main/java/org/apache/streampipes/connect/api/IParser.java
index 482bf9f..017adb6 100644
--- a/streampipes-connect-api/src/main/java/org/apache/streampipes/connect/api/IParser.java
+++ b/streampipes-connect-api/src/main/java/org/apache/streampipes/connect/api/IParser.java
@@ -19,6 +19,7 @@
 
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.model.connect.grounding.FormatDescription;
+import org.apache.streampipes.model.connect.guess.AdapterGuessInfo;
 import org.apache.streampipes.model.schema.EventSchema;
 
 import java.io.InputStream;
@@ -39,4 +40,12 @@
    * @return
    */
   EventSchema getEventSchema(List<byte[]> oneEvent);
+
+  default boolean supportsPreview() {
+    return false;
+  }
+
+  default AdapterGuessInfo getSchemaAndSample(List<byte[]> eventSample) throws ParseException {
+    throw new RuntimeException("Not yet implemented!");
+  }
 }
diff --git a/streampipes-connect-api/src/main/java/org/apache/streampipes/connect/api/exception/ParseException.java b/streampipes-connect-api/src/main/java/org/apache/streampipes/connect/api/exception/ParseException.java
index 2064f29..37c3ed3 100644
--- a/streampipes-connect-api/src/main/java/org/apache/streampipes/connect/api/exception/ParseException.java
+++ b/streampipes-connect-api/src/main/java/org/apache/streampipes/connect/api/exception/ParseException.java
@@ -19,10 +19,16 @@
 package org.apache.streampipes.connect.api.exception;
 
 public class ParseException extends RuntimeException {
+
     public ParseException() {}
 
     public ParseException(String message)
     {
         super(message);
     }
+
+    public ParseException(String message,
+                          Throwable throwable) {
+        super(message, throwable);
+    }
 }
diff --git a/streampipes-connect-container-master/pom.xml b/streampipes-connect-container-master/pom.xml
index 3d4207c..b1b9c26 100644
--- a/streampipes-connect-container-master/pom.xml
+++ b/streampipes-connect-container-master/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,32 +32,32 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-measurement-units</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-couchdb</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-user-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-data-explorer</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/AdapterMasterManagement.java b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/AdapterMasterManagement.java
index fc955bb..dc32b88 100644
--- a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/AdapterMasterManagement.java
+++ b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/AdapterMasterManagement.java
@@ -189,7 +189,7 @@
 
         LOG.info("Started adapter " + elementId + " on: " + baseUrl);
       } catch (NoServiceEndpointsAvailableException | URISyntaxException e) {
-        e.printStackTrace();
+        throw new AdapterException("Could not start adapter due to unavailable service endpoint", e);
       }
     }
   }
diff --git a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/DescriptionManagement.java b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/DescriptionManagement.java
index 834c764..da40e49 100644
--- a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/DescriptionManagement.java
+++ b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/DescriptionManagement.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.connect.container.master.management;
 
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.connect.adapter.AdapterRegistry;
 import org.apache.streampipes.connect.api.IFormat;
 import org.apache.streampipes.connect.api.exception.AdapterException;
@@ -25,6 +26,7 @@
 import org.apache.streampipes.model.connect.grounding.FormatDescription;
 import org.apache.streampipes.storage.api.IAdapterStorage;
 import org.apache.streampipes.storage.couchdb.CouchDbStorageManager;
+import org.apache.streampipes.storage.management.StorageDispatcher;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -55,6 +57,15 @@
                 .findFirst();
     }
 
+    public void deleteAdapterDescription(String id) throws SpRuntimeException {
+        var adapterStorage = CouchDbStorageManager.INSTANCE.getAdapterDescriptionStorage();
+        var adapter = adapterStorage.getAdapter(id);
+        if (!isAdapterUsed(adapter)) {
+            adapterStorage.deleteAdapter(id);
+        } else {
+            throw new SpRuntimeException("This adapter is used by an existing instance and cannot be deleted");
+        }
+    }
     public String getAssets(String baseUrl) throws AdapterException {
         return WorkerRestClient.getAssets(baseUrl);
     }
@@ -67,4 +78,12 @@
         return WorkerRestClient.getDocumentationAsset(baseUrl);
     }
 
+    private boolean isAdapterUsed(AdapterDescription adapter) {
+        var allAdapters = StorageDispatcher.INSTANCE.getNoSqlStore().getAdapterInstanceStorage().getAllAdapters();
+
+        return allAdapters
+          .stream()
+          .anyMatch(runningAdapter -> runningAdapter.getAppId().equals(adapter.getAppId()));
+    }
+
 }
diff --git a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/GuessManagement.java b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/GuessManagement.java
index 0d867bb..de66c54 100644
--- a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/GuessManagement.java
+++ b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/GuessManagement.java
@@ -26,18 +26,21 @@
 import org.apache.http.entity.ContentType;
 import org.apache.http.util.EntityUtils;
 import org.apache.streampipes.commons.exceptions.NoServiceEndpointsAvailableException;
-import org.apache.streampipes.connect.api.exception.AdapterException;
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
+import org.apache.streampipes.connect.adapter.model.pipeline.AdapterEventPreviewPipeline;
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.connect.api.exception.WorkerAdapterException;
 import org.apache.streampipes.connect.container.master.util.WorkerPaths;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import org.apache.streampipes.model.connect.guess.AdapterEventPreview;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
-import org.apache.streampipes.model.message.ErrorMessage;
+import org.apache.streampipes.model.connect.guess.GuessTypeInfo;
 import org.apache.streampipes.serializers.json.JacksonSerializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.util.Map;
 
 public class GuessManagement {
 
@@ -48,8 +51,7 @@
         this.workerUrlProvider = new WorkerUrlProvider();
     }
 
-    public GuessSchema guessSchema(AdapterDescription adapterDescription) throws AdapterException, ParseException, WorkerAdapterException {
-        try {
+    public GuessSchema guessSchema(AdapterDescription adapterDescription) throws ParseException, WorkerAdapterException, NoServiceEndpointsAvailableException, IOException {
             String workerUrl = workerUrlProvider.getWorkerBaseUrl(adapterDescription.getAppId());
 
             workerUrl = workerUrl + WorkerPaths.getGuessSchemaPath();
@@ -67,18 +69,14 @@
             String responseString = EntityUtils.toString(httpResponse.getEntity());
 
             if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
-                return mapper.readValue(responseString, GuessSchema.class);
-            }  else {
-                    ErrorMessage errorMessage = mapper.readValue(responseString, ErrorMessage.class);
-
-                    LOG.error(errorMessage.getElementName());
-                    throw new WorkerAdapterException(errorMessage);
+              return mapper.readValue(responseString, GuessSchema.class);
+            } else {
+              var exception = mapper.readValue(responseString, SpConfigurationException.class);
+              throw new WorkerAdapterException(exception.getMessage(), exception.getCause());
             }
-
-        } catch (IOException | NoServiceEndpointsAvailableException e) {
-            LOG.error(e.getMessage());
-            throw new AdapterException("Error in connect worker: ", e);
-        }
     }
 
+  public Map<String, GuessTypeInfo> performAdapterEventPreview(AdapterEventPreview previewRequest) {
+      return new AdapterEventPreviewPipeline(previewRequest).makePreview();
+  }
 }
diff --git a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/WorkerAdministrationManagement.java b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/WorkerAdministrationManagement.java
index 9d3b5e3..1124929 100644
--- a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/WorkerAdministrationManagement.java
+++ b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/WorkerAdministrationManagement.java
@@ -49,7 +49,7 @@
             // only install once adapter description per service group
             boolean alreadyInstalled = alreadyRegisteredAdapters
                     .stream()
-                    .anyMatch(a -> a.getAppId().equals(adapterDescription.getAppId()) && a.getCorrespondingServiceGroup().equals(adapterDescription.getCorrespondingServiceGroup()));
+                    .anyMatch(a -> a.getAppId().equals(adapterDescription.getAppId()));
             if (!alreadyInstalled) {
                 this.adapterDescriptionStorage.storeAdapter(adapterDescription);
             }
diff --git a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/WorkerRestClient.java b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/WorkerRestClient.java
index 8c9f107..241b93f 100644
--- a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/WorkerRestClient.java
+++ b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/WorkerRestClient.java
@@ -18,8 +18,12 @@
 
 package org.apache.streampipes.connect.container.master.management;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpResponse;
 import org.apache.http.client.fluent.Request;
 import org.apache.http.entity.ContentType;
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.container.master.util.WorkerPaths;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
@@ -37,6 +41,7 @@
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 /**
@@ -99,66 +104,75 @@
 
     public static void startAdapter(String url,
                                     AdapterDescription ad) throws AdapterException {
-        try {
-            logger.info("Trying to start adapter on endpoint: " + url);
-
-            String adapterDescription = JacksonSerializer.getObjectMapper().writeValueAsString(ad);
-
-            String responseString = Request.Post(url)
-                    .bodyString(adapterDescription, ContentType.APPLICATION_JSON)
-                    .connectTimeout(1000)
-                    .socketTimeout(100000)
-                    .execute().returnContent().asString();
-
-            logger.info("Adapter started on endpoint: " + url);
-
-        } catch (IOException e) {
-            logger.error("Adapter did not start", e);
-            throw new AdapterException("Adapter with URL: " + url + " did not start");
-        }
+        logger.info("Trying to start adapter on endpoint {} ", url);
+        triggerAdapterStateChange(ad, url, "started");
     }
 
 
     public static void stopAdapter(AdapterDescription ad,
                                    String url) throws AdapterException {
 
-        // Stop execution of adapter
-        try {
-            logger.info("Trying to stop adapter on endpoint: " + url);
+        logger.info("Trying to stop adapter on endpoint {} ", url);
+        triggerAdapterStateChange(ad, url, "stopped");
+    }
 
+    private static void triggerAdapterStateChange(AdapterDescription ad,
+                                            String url,
+                                            String action) throws AdapterException {
+        try {
             String adapterDescription = JacksonSerializer.getObjectMapper().writeValueAsString(ad);
 
-            // TODO change this to a delete request
-            String responseString = Request.Post(url)
-                    .bodyString(adapterDescription, ContentType.APPLICATION_JSON)
-                    .connectTimeout(1000)
-                    .socketTimeout(100000)
-                    .execute().returnContent().asString();
+            var response = triggerPost(url, adapterDescription);
+            var responseString = getResponseBody(response);
 
-            logger.info("Adapter stopped on endpoint: " + url + " with Response: " + responseString);
+            if (response.getStatusLine().getStatusCode() != 200) {
+                var exception = getSerializer().readValue(responseString, AdapterException.class);
+                throw new AdapterException(exception.getMessage(), exception.getCause());
+            }
+
+            logger.info("Adapter {} on endpoint: " + url + " with Response: " + responseString);
 
         } catch (IOException e) {
-            logger.error("Adapter was not stopped successfully", e);
-            throw new AdapterException("Adapter was not stopped successfully with url: " + url);
+            logger.error("Adapter was not {} successfully", action, e);
+            throw new AdapterException("Adapter was not " + action + " successfully with url " + url, e);
         }
+    }
 
+    private static String getResponseBody(HttpResponse response) throws IOException {
+        return IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
+    }
+
+    private static HttpResponse triggerPost(String url,
+                                            String payload) throws IOException {
+        return Request.Post(url)
+          .bodyString(payload, ContentType.APPLICATION_JSON)
+          .connectTimeout(1000)
+          .socketTimeout(100000)
+          .execute().returnResponse();
     }
 
     public static RuntimeOptionsResponse getConfiguration(String workerEndpoint,
                                                           String appId,
-                                                          RuntimeOptionsRequest runtimeOptionsRequest) throws AdapterException {
+                                                          RuntimeOptionsRequest runtimeOptionsRequest) throws AdapterException, SpConfigurationException {
         String url = workerEndpoint + WorkerPaths.getRuntimeResolvablePath(appId);
 
         try {
             String payload = JacksonSerializer.getObjectMapper().writeValueAsString(runtimeOptionsRequest);
-            String responseString = Request.Post(url)
+            var response = Request.Post(url)
                        .bodyString(payload, ContentType.APPLICATION_JSON)
                        .connectTimeout(1000)
                        .socketTimeout(100000)
-                       .execute().returnContent().asString();
+                       .execute()
+                        .returnResponse();
 
-            return JacksonSerializer.getObjectMapper().readValue(responseString, RuntimeOptionsResponse.class);
+            String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
 
+            if (response.getStatusLine().getStatusCode() == 200) {
+                return getSerializer().readValue(responseString, RuntimeOptionsResponse.class);
+            } else {
+                var exception = getSerializer().readValue(responseString, SpConfigurationException.class);
+                throw new SpConfigurationException(exception.getMessage(), exception.getCause());
+            }
         } catch (IOException e) {
             e.printStackTrace();
             throw new AdapterException("Could not resolve runtime configurations from " + url);
@@ -245,5 +259,9 @@
     private static IAdapterStorage getAdapterStorage() {
         return StorageDispatcher.INSTANCE.getNoSqlStore().getAdapterInstanceStorage();
     }
+
+    private static ObjectMapper getSerializer() {
+        return JacksonSerializer.getObjectMapper();
+    }
 }
 
diff --git a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/util/WorkerPaths.java b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/util/WorkerPaths.java
index f3af79b..1a48828 100644
--- a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/util/WorkerPaths.java
+++ b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/util/WorkerPaths.java
@@ -60,8 +60,7 @@
     SpServiceUrlProvider serviceUrlProvider = SpServiceUrlProvider.ADAPTER;
     String endpointUrl = new ExtensionsServiceEndpointGenerator(appId, serviceUrlProvider).getEndpointResourceUrl();
     URI uri = new URI(endpointUrl);
-    String baseUrl = uri.getScheme() + "://" + uri.getAuthority();
-    return baseUrl;
+    return uri.getScheme() + "://" + uri.getAuthority();
   }
 
 
diff --git a/streampipes-connect-container-worker/pom.xml b/streampipes-connect-container-worker/pom.xml
index dc1e74b..09dd177 100644
--- a/streampipes-connect-container-worker/pom.xml
+++ b/streampipes-connect-container-worker/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,37 +32,37 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-extensions-base</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-rest-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-serializers-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <!-- External dependencies -->
 
diff --git a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/management/AdapterWorkerManagement.java b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/management/AdapterWorkerManagement.java
index 1c8d606..f250ac7 100644
--- a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/management/AdapterWorkerManagement.java
+++ b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/management/AdapterWorkerManagement.java
@@ -80,11 +80,9 @@
 
         IAdapter<?> adapter = RunningAdapterInstances.INSTANCE.removeAdapter(elementId);
 
-        if (adapter == null) {
-            throw new AdapterException("Adapter with id " + elementId + " was not found in this container and cannot be stopped.");
+        if (adapter != null) {
+            adapter.stopAdapter();
         }
-
-        adapter.stopAdapter();
     }
 
 }
diff --git a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/management/GuessManagement.java b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/management/GuessManagement.java
index 41f81de..362c63a 100644
--- a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/management/GuessManagement.java
+++ b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/management/GuessManagement.java
@@ -60,8 +60,7 @@
 
             throw new ParseException(errorClass + e.getMessage());
         } catch (Exception e) {
-            LOG.error("Unknown Error: " + e.toString());
-            throw new AdapterException(e.toString());
+            throw new AdapterException(e.getMessage(), e);
         }
 
         return guessSchema;
diff --git a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/AdapterWorkerResource.java b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/AdapterWorkerResource.java
index e423590..9aa69c8 100644
--- a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/AdapterWorkerResource.java
+++ b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/AdapterWorkerResource.java
@@ -20,6 +20,7 @@
 
 import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.container.worker.management.AdapterWorkerManagement;
+import org.apache.streampipes.model.StreamPipesErrorMessage;
 import org.apache.streampipes.model.connect.adapter.AdapterSetDescription;
 import org.apache.streampipes.model.connect.adapter.AdapterStreamDescription;
 import org.apache.streampipes.model.message.Notifications;
@@ -65,14 +66,13 @@
 
         try {
             adapterManagement.invokeStreamAdapter(adapterStreamDescription);
+            String responseMessage = "Stream adapter with id " + adapterStreamDescription.getUri() + " successfully started";
+            logger.info(responseMessage);
+            return ok(Notifications.success(responseMessage));
         } catch (AdapterException e) {
             logger.error("Error while starting adapter with id " + adapterStreamDescription.getUri(), e);
-            return ok(Notifications.error(e.getMessage()));
+            return serverError(StreamPipesErrorMessage.from(e));
         }
-        String responseMessage = "Stream adapter with id " + adapterStreamDescription.getUri() + " successfully started";
-
-        logger.info(responseMessage);
-        return ok(Notifications.success(responseMessage));
     }
 
     @POST
@@ -82,17 +82,20 @@
     @Produces(MediaType.APPLICATION_JSON)
     public Response stopStreamAdapter(AdapterStreamDescription adapterStreamDescription) {
 
+        String responseMessage;
         try {
-            adapterManagement.stopStreamAdapter(adapterStreamDescription);
+            if (adapterStreamDescription.isRunning()) {
+                adapterManagement.stopStreamAdapter(adapterStreamDescription);
+                responseMessage = "Stream adapter with id " + adapterStreamDescription.getElementId() + " successfully stopped";
+            } else {
+                responseMessage = "Stream adapter with id " + adapterStreamDescription.getElementId() + " seems not to be running";
+            }
+            logger.info(responseMessage);
+            return ok(Notifications.success(responseMessage));
         } catch (AdapterException e) {
-            logger.error("Error while stopping adapter with id " + adapterStreamDescription.getUri(), e);
-            return ok(Notifications.error(e.getMessage()));
+            logger.error("Error while stopping adapter with id " + adapterStreamDescription.getElementId(), e);
+            return serverError(StreamPipesErrorMessage.from(e));
         }
-
-        String responseMessage = "Stream adapter with id " + adapterStreamDescription.getUri() + " successfully stopped";
-
-        logger.info(responseMessage);
-        return ok(Notifications.success(responseMessage));
     }
 
     @POST
diff --git a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/GuessResource.java b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/GuessResource.java
index 39d8784..c357a54 100644
--- a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/GuessResource.java
+++ b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/GuessResource.java
@@ -18,11 +18,11 @@
 
 package org.apache.streampipes.connect.container.worker.rest;
 
+import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.connect.container.worker.management.GuessManagement;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
-import org.apache.streampipes.model.message.Notifications;
 import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
 import org.apache.streampipes.rest.shared.impl.AbstractSharedRestInterface;
 import org.slf4j.Logger;
@@ -62,10 +62,10 @@
           return ok(result);
       } catch (ParseException e) {
           logger.error("Error while parsing events: ", e);
-          return serverError(Notifications.error(e.getMessage()));
-      } catch (Exception e) {
-          logger.error("Error while guess schema for AdapterDescription: " + adapterDescription.getElementId(), e);
-          return serverError(Notifications.error(e.getMessage()));
+          return serverError(e);
+      } catch (AdapterException e) {
+          logger.error("Error while guessing schema for AdapterDescription: {}, {}", adapterDescription.getElementId(), e.getMessage());
+          return serverError(e);
       }
 
   }
diff --git a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/RuntimeResolvableResource.java b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/RuntimeResolvableResource.java
index 92a81fd..72a2094 100644
--- a/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/RuntimeResolvableResource.java
+++ b/streampipes-connect-container-worker/src/main/java/org/apache/streampipes/connect/container/worker/rest/RuntimeResolvableResource.java
@@ -18,6 +18,8 @@
 
 package org.apache.streampipes.connect.container.worker.rest;
 
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.connect.api.Connector;
 import org.apache.streampipes.connect.container.worker.management.RuntimeResovable;
 import org.apache.streampipes.container.api.ResolvesContainerProvidedOptions;
@@ -47,15 +49,21 @@
         RuntimeOptionsResponse response;
         RuntimeResolvableRequestHandler handler = new RuntimeResolvableRequestHandler();
 
-        if (connector instanceof ResolvesContainerProvidedOptions) {
-            response = handler.handleRuntimeResponse((ResolvesContainerProvidedOptions) connector, runtimeOptionsRequest);
-        } else if (connector instanceof SupportsRuntimeConfig) {
-            response = handler.handleRuntimeResponse((SupportsRuntimeConfig) connector, runtimeOptionsRequest);
-        } else {
-            throw new WebApplicationException(javax.ws.rs.core.Response.Status.BAD_REQUEST);
+        try {
+            if (connector instanceof ResolvesContainerProvidedOptions) {
+                response = handler.handleRuntimeResponse((ResolvesContainerProvidedOptions) connector, runtimeOptionsRequest);
+                return ok(response);
+            } else if (connector instanceof SupportsRuntimeConfig) {
+                response = handler.handleRuntimeResponse((SupportsRuntimeConfig) connector, runtimeOptionsRequest);
+                return ok(response);
+            } else {
+                throw new SpRuntimeException("This element does not support dynamic options - is the pipeline element description up to date?");
+            }
+        } catch (SpConfigurationException e) {
+            return javax.ws.rs.core.Response
+              .status(400)
+              .entity(e)
+              .build();
         }
-
-        return ok(response);
     }
-
 }
diff --git a/streampipes-connect-container-worker/src/test/java/org/apache/streampipes/connect/container/worker/management/AdapterWorkerManagementTest.java b/streampipes-connect-container-worker/src/test/java/org/apache/streampipes/connect/container/worker/management/AdapterWorkerManagementTest.java
index 631f3f9..f16a2e7 100644
--- a/streampipes-connect-container-worker/src/test/java/org/apache/streampipes/connect/container/worker/management/AdapterWorkerManagementTest.java
+++ b/streampipes-connect-container-worker/src/test/java/org/apache/streampipes/connect/container/worker/management/AdapterWorkerManagementTest.java
@@ -42,22 +42,6 @@
 public class AdapterWorkerManagementTest {
 
     @Test
-    public void stopStreamAdapterFail() {
-        String expected = "Adapter with id http://test.de was not found in this container and cannot be stopped.";
-        AdapterStreamDescription asd = new GenericAdapterStreamDescription();
-        asd.setUri("http://test.de");
-
-        AdapterWorkerManagement adapterManagement = new AdapterWorkerManagement();
-
-        try {
-            adapterManagement.stopStreamAdapter(asd);
-            fail();
-        } catch (AdapterException e) {
-            assertEquals(expected, e.getMessage());
-        }
-    }
-
-    @Test
     public void stopStreamAdapterSuccess() throws AdapterException {
         TestAdapter testAdapter = getTestAdapterInstance();
         RunningAdapterInstances.INSTANCE.addAdapter("http://t.de/", testAdapter, null);
@@ -69,22 +53,6 @@
     }
 
     @Test
-    public void stopSetAdapterFail() {
-        String expected = "Adapter with id http://test.de was not found in this container and cannot be stopped.";
-        AdapterSetDescription asd = new GenericAdapterSetDescription();
-        asd.setUri("http://test.de");
-
-        AdapterWorkerManagement adapterManagement = new AdapterWorkerManagement();
-
-        try {
-            adapterManagement.stopSetAdapter(asd);
-            fail();
-        } catch (AdapterException e) {
-            assertEquals(expected, e.getMessage());
-        }
-    }
-
-    @Test
     public void stopSetAdapterSuccess() throws AdapterException {
         TestAdapter testAdapter = getTestAdapterInstance();
 
diff --git a/streampipes-connect/pom.xml b/streampipes-connect/pom.xml
index 2f36435..7517b49 100755
--- a/streampipes-connect/pom.xml
+++ b/streampipes-connect/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,72 +32,72 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect-api</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-smile</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-cbor</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-fst</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-measurement-units</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-kafka</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-jms</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-mqtt</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-rest-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-serializers-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencis -->
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/Adapter.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/Adapter.java
index 8b6ee89..d5d495a 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/Adapter.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/Adapter.java
@@ -22,29 +22,17 @@
 import org.apache.streampipes.config.backend.BackendConfig;
 import org.apache.streampipes.config.backend.SpProtocol;
 import org.apache.streampipes.connect.adapter.model.pipeline.AdapterPipeline;
-import org.apache.streampipes.connect.adapter.preprocessing.transform.stream.DuplicateFilterPipelineElement;
-import org.apache.streampipes.connect.api.IAdapterPipelineElement;
-import org.apache.streampipes.connect.adapter.preprocessing.elements.*;
+import org.apache.streampipes.connect.adapter.preprocessing.elements.SendToJmsAdapterSink;
+import org.apache.streampipes.connect.adapter.preprocessing.elements.SendToKafkaAdapterSink;
+import org.apache.streampipes.connect.adapter.preprocessing.elements.SendToMqttAdapterSink;
 import org.apache.streampipes.connect.api.IAdapter;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
-import org.apache.streampipes.model.connect.rules.TransformationRuleDescription;
-import org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription;
-import org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription;
-import org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription;
-import org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription;
-import org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription;
 import org.apache.streampipes.model.grounding.JmsTransportProtocol;
 import org.apache.streampipes.model.grounding.KafkaTransportProtocol;
 import org.apache.streampipes.model.grounding.MqttTransportProtocol;
 import org.apache.streampipes.model.grounding.TransportProtocol;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
 
 public abstract class Adapter<T extends AdapterDescription> implements IAdapter<T> {
-    Logger logger = LoggerFactory.getLogger(Adapter.class);
 
     private boolean debug;
 
@@ -100,97 +88,7 @@
     }
 
     private AdapterPipeline getAdapterPipeline(T adapterDescription) {
-
-        List<IAdapterPipelineElement> pipelineElements = new ArrayList<>();
-
-        // Must be before the schema transformations to ensure that user can move this event property
-        AddTimestampRuleDescription timestampTransformationRuleDescription = getTimestampRule(adapterDescription);
-        if (timestampTransformationRuleDescription != null) {
-            pipelineElements.add(new AddTimestampPipelineElement(
-                    timestampTransformationRuleDescription.getRuntimeKey()));
-        }
-
-        AddValueTransformationRuleDescription valueTransformationRuleDescription = getAddValueRule(adapterDescription);
-        if (valueTransformationRuleDescription != null) {
-            pipelineElements.add(new AddValuePipelineElement(
-                    valueTransformationRuleDescription.getRuntimeKey(),
-                    valueTransformationRuleDescription.getStaticValue()));
-        }
-
-
-        // first transform schema before transforming vales
-        // value rules should use unique keys for of new schema
-        pipelineElements.add(new TransformSchemaAdapterPipelineElement(adapterDescription.getSchemaRules()));
-        pipelineElements.add(new TransformValueAdapterPipelineElement(adapterDescription.getValueRules()));
-
-
-        RemoveDuplicatesTransformationRuleDescription duplicatesTransformationRuleDescription = getRemoveDuplicateRule(adapterDescription);
-        if (duplicatesTransformationRuleDescription != null) {
-            pipelineElements.add(new DuplicateFilterPipelineElement(duplicatesTransformationRuleDescription.getFilterTimeWindow()));
-        }
-
-        TransformStreamAdapterElement transformStreamAdapterElement = new TransformStreamAdapterElement();
-        EventRateTransformationRuleDescription eventRateTransformationRuleDescription = getEventRateTransformationRule(adapterDescription);
-        if (eventRateTransformationRuleDescription != null) {
-            transformStreamAdapterElement.addStreamTransformationRuleDescription(eventRateTransformationRuleDescription);
-        }
-        pipelineElements.add(transformStreamAdapterElement);
-
-        // Needed when adapter is (
-        if (adapterDescription.getEventGrounding() != null && adapterDescription.getEventGrounding().getTransportProtocol() != null
-                && adapterDescription.getEventGrounding().getTransportProtocol().getBrokerHostname() != null) {
-            return new AdapterPipeline(pipelineElements, getAdapterSink(adapterDescription));
-        }
-
-        return new AdapterPipeline(pipelineElements);
-    }
-
-    private SendToBrokerAdapterSink<?> getAdapterSink(AdapterDescription adapterDescription) {
-        SpProtocol prioritizedProtocol =
-                BackendConfig.INSTANCE.getMessagingSettings().getPrioritizedProtocols().get(0);
-
-        if (GroundingService.isPrioritized(prioritizedProtocol, JmsTransportProtocol.class)) {
-            return new SendToJmsAdapterSink(adapterDescription);
-        }
-        else if (GroundingService.isPrioritized(prioritizedProtocol, KafkaTransportProtocol.class)) {
-            return new SendToKafkaAdapterSink(adapterDescription);
-        }
-        else {
-            return new SendToMqttAdapterSink(adapterDescription);
-        }
-    }
-
-    private RemoveDuplicatesTransformationRuleDescription getRemoveDuplicateRule(T adapterDescription) {
-        return getRule(adapterDescription, RemoveDuplicatesTransformationRuleDescription.class);
-    }
-
-    private EventRateTransformationRuleDescription getEventRateTransformationRule(T adapterDescription) {
-        return getRule(adapterDescription, EventRateTransformationRuleDescription.class);
-    }
-
-    private AddTimestampRuleDescription getTimestampRule(T adapterDescription) {
-        return getRule(adapterDescription, AddTimestampRuleDescription.class);
-    }
-
-    private AddValueTransformationRuleDescription getAddValueRule(T adapterDescription) {
-        return getRule(adapterDescription, AddValueTransformationRuleDescription.class);
-    }
-
-    private CorrectionValueTransformationRuleDescription getCorrectionValueRule(T adapterDescription) {
-        return getRule(adapterDescription, CorrectionValueTransformationRuleDescription.class);
-    }
-
-    private <G extends TransformationRuleDescription> G getRule(T adapterDescription, Class<G> type) {
-
-        if (adapterDescription != null) {
-            for (TransformationRuleDescription tr : adapterDescription.getRules()) {
-                if (type.isInstance(tr)) {
-                    return type.cast(tr);
-                }
-            }
-        }
-
-        return null;
+        return new AdapterPipelineGenerator().generatePipeline(adapterDescription);
     }
 
     @Override
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/AdapterPipelineGenerator.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/AdapterPipelineGenerator.java
new file mode 100644
index 0000000..76ecd9f
--- /dev/null
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/AdapterPipelineGenerator.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.connect.adapter;
+
+import org.apache.streampipes.config.backend.BackendConfig;
+import org.apache.streampipes.connect.adapter.model.pipeline.AdapterPipeline;
+import org.apache.streampipes.connect.adapter.preprocessing.elements.*;
+import org.apache.streampipes.connect.adapter.preprocessing.transform.stream.DuplicateFilterPipelineElement;
+import org.apache.streampipes.connect.api.IAdapterPipelineElement;
+import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import org.apache.streampipes.model.connect.rules.TransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.schema.SchemaTransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.value.*;
+import org.apache.streampipes.model.grounding.JmsTransportProtocol;
+import org.apache.streampipes.model.grounding.KafkaTransportProtocol;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class AdapterPipelineGenerator {
+
+  public AdapterPipeline generatePipeline(AdapterDescription adapterDescription) {
+
+    var pipelineElements = makeAdapterPipelineElements(adapterDescription.getRules());
+
+    var duplicatesTransformationRuleDescription = getRemoveDuplicateRule(adapterDescription.getRules());
+    if (duplicatesTransformationRuleDescription != null) {
+      pipelineElements.add(new DuplicateFilterPipelineElement(duplicatesTransformationRuleDescription.getFilterTimeWindow()));
+    }
+
+    var transformStreamAdapterElement = new TransformStreamAdapterElement();
+    var eventRateTransformationRuleDescription = getEventRateTransformationRule(adapterDescription.getRules());
+    if (eventRateTransformationRuleDescription != null) {
+      transformStreamAdapterElement.addStreamTransformationRuleDescription(eventRateTransformationRuleDescription);
+    }
+    pipelineElements.add(transformStreamAdapterElement);
+
+    // TODO decide what was meant with this comment
+    // Needed when adapter is (
+    if (adapterDescription.getEventGrounding() != null && adapterDescription.getEventGrounding().getTransportProtocol() != null
+      && adapterDescription.getEventGrounding().getTransportProtocol().getBrokerHostname() != null) {
+      return new AdapterPipeline(pipelineElements, getAdapterSink(adapterDescription));
+    }
+
+    return new AdapterPipeline(pipelineElements);
+  }
+
+  public List<IAdapterPipelineElement> makeAdapterPipelineElements(List<TransformationRuleDescription> rules) {
+    List<IAdapterPipelineElement> pipelineElements = new ArrayList<>();
+
+    // Must be before the schema transformations to ensure that user can move this event property
+    var timestampTransformationRuleDescription = getTimestampRule(rules);
+    if (timestampTransformationRuleDescription != null) {
+      pipelineElements.add(new AddTimestampPipelineElement(
+        timestampTransformationRuleDescription.getRuntimeKey()));
+    }
+
+    var valueTransformationRuleDescription = getAddValueRule(rules);
+    if (valueTransformationRuleDescription != null) {
+      pipelineElements.add(new AddValuePipelineElement(
+        valueTransformationRuleDescription.getRuntimeKey(),
+        valueTransformationRuleDescription.getStaticValue()));
+    }
+
+    // first transform schema before transforming vales
+    // value rules should use unique keys for of new schema
+    pipelineElements.add(new TransformSchemaAdapterPipelineElement(getSchemaRules(rules)));
+    pipelineElements.add(new TransformValueAdapterPipelineElement(getValueRules(rules)));
+
+    return pipelineElements;
+  }
+
+  private SendToBrokerAdapterSink<?> getAdapterSink(AdapterDescription adapterDescription) {
+    var prioritizedProtocol =
+      BackendConfig.INSTANCE.getMessagingSettings().getPrioritizedProtocols().get(0);
+
+    if (GroundingService.isPrioritized(prioritizedProtocol, JmsTransportProtocol.class)) {
+      return new SendToJmsAdapterSink(adapterDescription);
+    }
+    else if (GroundingService.isPrioritized(prioritizedProtocol, KafkaTransportProtocol.class)) {
+      return new SendToKafkaAdapterSink(adapterDescription);
+    }
+    else {
+      return new SendToMqttAdapterSink(adapterDescription);
+    }
+  }
+
+  private RemoveDuplicatesTransformationRuleDescription getRemoveDuplicateRule(List<TransformationRuleDescription> rules) {
+    return getRule(rules, RemoveDuplicatesTransformationRuleDescription.class);
+  }
+
+  private EventRateTransformationRuleDescription getEventRateTransformationRule(List<TransformationRuleDescription> rules) {
+    return getRule(rules, EventRateTransformationRuleDescription.class);
+  }
+
+  private AddTimestampRuleDescription getTimestampRule(List<TransformationRuleDescription> rules) {
+    return getRule(rules, AddTimestampRuleDescription.class);
+  }
+
+  private AddValueTransformationRuleDescription getAddValueRule(List<TransformationRuleDescription> rules) {
+    return getRule(rules, AddValueTransformationRuleDescription.class);
+  }
+
+  private <G extends TransformationRuleDescription> G getRule(List<TransformationRuleDescription> rules,
+                                                              Class<G> type) {
+
+    if (rules != null) {
+      for (TransformationRuleDescription tr : rules) {
+        if (type.isInstance(tr)) {
+          return type.cast(tr);
+        }
+      }
+    }
+
+    return null;
+  }
+
+  private List<TransformationRuleDescription> getValueRules(List<TransformationRuleDescription> rules) {
+    return rules
+      .stream()
+      .filter(r -> r instanceof ValueTransformationRuleDescription && !(r instanceof AddTimestampRuleDescription))
+      .collect(Collectors.toList());
+  }
+
+  private List<TransformationRuleDescription> getSchemaRules(List<TransformationRuleDescription> rules) {
+    return rules
+      .stream()
+      .filter(r -> r instanceof SchemaTransformationRuleDescription)
+      .collect(Collectors.toList());
+  }
+}
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/csv/CsvParser.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/csv/CsvParser.java
index 4f6b873..0b3e6be 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/csv/CsvParser.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/csv/CsvParser.java
@@ -19,20 +19,23 @@
 package org.apache.streampipes.connect.adapter.format.csv;
 
 
-import org.apache.streampipes.connect.api.EmitBinaryEvent;
 import org.apache.streampipes.connect.adapter.model.generic.Parser;
 import org.apache.streampipes.connect.adapter.sdk.ParameterExtractor;
+import org.apache.streampipes.connect.adapter.util.DatatypeUtils;
+import org.apache.streampipes.connect.api.EmitBinaryEvent;
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.model.connect.grounding.FormatDescription;
+import org.apache.streampipes.model.connect.guess.AdapterGuessInfo;
+import org.apache.streampipes.model.connect.guess.GuessTypeInfo;
 import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.schema.EventSchema;
-import org.apache.streampipes.vocabulary.XSD;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 
@@ -81,7 +84,13 @@
     }
 
     @Override
-    public EventSchema getEventSchema(List<byte[]> oneEvent) {
+    public boolean supportsPreview() {
+        return true;
+    }
+
+    @Override
+    public AdapterGuessInfo getSchemaAndSample(List<byte[]> oneEvent) {
+        var sample = new HashMap<String, GuessTypeInfo>();
         String[] keys;
         String[] data;
 
@@ -99,28 +108,20 @@
         EventSchema resultSchema = new EventSchema();
         for (int i = 0; i < keys.length; i++) {
             EventPropertyPrimitive p = new EventPropertyPrimitive();
+            var runtimeType = DatatypeUtils.getXsdDatatype(data[i], true);
+            var convertedValue = DatatypeUtils.convertValue(data[i], runtimeType);
             p.setRuntimeName(keys[i]);
-            p.setRuntimeType(getTypeString(data[i]));
+            p.setRuntimeType(runtimeType);
+            sample.put(keys[i], new GuessTypeInfo(DatatypeUtils.getCanonicalTypeClassName(data[i], true), convertedValue));
             resultSchema.addEventProperty(p);
         }
 
-        return resultSchema;
+        return new AdapterGuessInfo(resultSchema, sample);
     }
 
-    private String getTypeString(String o) {
-
-        try {
-            Double.parseDouble(o);
-            return XSD._float.toString();
-        } catch (NumberFormatException e) {
-
-        }
-
-        if (o.equalsIgnoreCase("true") || o.equalsIgnoreCase("false")) {
-            return XSD._boolean.toString();
-        }
-
-        return XSD._string.toString();
+    @Override
+    public EventSchema getEventSchema(List<byte[]> oneEvent) {
+        return getSchemaAndSample(oneEvent).getEventSchema();
     }
 
 
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/AbstractJsonFormat.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/AbstractJsonFormat.java
index a7116ae..1da9b16 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/AbstractJsonFormat.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/AbstractJsonFormat.java
@@ -21,7 +21,6 @@
 import org.apache.streampipes.connect.api.IFormat;
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.dataformat.json.JsonDataFormatDefinition;
-import org.apache.streampipes.model.schema.EventSchema;
 
 import java.util.Map;
 
@@ -30,8 +29,6 @@
 
   @Override
   public Map<String, Object> parse(byte[] object) throws ParseException {
-    EventSchema resultSchema = new EventSchema();
-
     JsonDataFormatDefinition jsonDefinition = new JsonDataFormatDefinition();
 
     Map<String, Object> result = null;
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/object/JsonObjectParser.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/object/JsonObjectParser.java
index 3419bc9..06c5cf5 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/object/JsonObjectParser.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/object/JsonObjectParser.java
@@ -20,24 +20,26 @@
 
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
-import org.apache.streampipes.connect.api.EmitBinaryEvent;
-import org.apache.streampipes.connect.adapter.model.generic.Parser;
 import org.apache.streampipes.connect.adapter.format.util.JsonEventProperty;
+import org.apache.streampipes.connect.adapter.model.generic.Parser;
+import org.apache.streampipes.connect.api.EmitBinaryEvent;
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.dataformat.json.JsonDataFormatDefinition;
 import org.apache.streampipes.model.connect.grounding.FormatDescription;
+import org.apache.streampipes.model.connect.guess.AdapterGuessInfo;
+import org.apache.streampipes.model.connect.guess.GuessTypeInfo;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 public class JsonObjectParser extends Parser {
 
@@ -75,9 +77,17 @@
 
     @Override
     public EventSchema getEventSchema(List<byte[]> oneEvent) {
-        EventSchema resultSchema = new EventSchema();
+        return getSchemaAndSample(oneEvent).getEventSchema();
+    }
 
-//        resultSchema.setEventProperties(Arrays.asList(EpProperties.timestampProperty("timestamp")));
+    @Override
+    public boolean supportsPreview() {
+        return true;
+    }
+
+    @Override
+    public AdapterGuessInfo getSchemaAndSample(List<byte[]> eventSample) throws ParseException {
+        EventSchema resultSchema = new EventSchema();
 
         JsonDataFormatDefinition jsonDefinition = new JsonDataFormatDefinition();
 
@@ -85,107 +95,22 @@
         Map<String, Object> exampleEvent = null;
 
         try {
-            exampleEvent = jsonDefinition.toMap(oneEvent.get(0));
-        } catch (SpRuntimeException e) {
-            e.printStackTrace();
-        }
+            exampleEvent = jsonDefinition.toMap(eventSample.get(0));
+            var sample = exampleEvent
+              .entrySet()
+              .stream()
+              .collect(Collectors.toMap(Map.Entry::getKey, e ->
+                new GuessTypeInfo(e.getValue().getClass().getCanonicalName(), e.getValue())));
 
-        for (Map.Entry<String, Object> entry : exampleEvent.entrySet())
-        {
-//            System.out.println(entry.getKey() + "/" + entry.getValue());
-            EventProperty p = JsonEventProperty.getEventProperty(entry.getKey(), entry.getValue());
+            for (Map.Entry<String, Object> entry : exampleEvent.entrySet()) {
+                EventProperty p = JsonEventProperty.getEventProperty(entry.getKey(), entry.getValue());
 
-            resultSchema.addEventProperty(p);
-
-        }
-
-        return resultSchema;
-    }
-
-    public Map<String, Object> parseObject(javax.json.stream.JsonParser jsonParser, boolean root, int start) {
-        // this variable is needed to skip the first object start
-        String mapKey = "";
-        Map<String, Object> result = new HashMap<>();
-        List<Object> arr = null;
-
-        while (jsonParser.hasNext()) {
-            javax.json.stream.JsonParser.Event event = jsonParser.next();
-            switch (event) {
-                case KEY_NAME:
-                    mapKey = jsonParser.getString();
-                    logger.debug("key: " + mapKey );
-                    break;
-                case START_OBJECT:
-                    if (start == 0) {
-                        Map<String, Object> ob = parseObject(jsonParser, false, 0);
-                        if (arr == null) {
-                            result.put(mapKey, ob);
-                        } else {
-                            arr.add(ob);
-                        }
-                    } else {
-                        start--;
-                    }
-                    logger.debug("start object");
-                    break;
-                case END_OBJECT:
-
-                    logger.debug("end object");
-                    return result;
-                case START_ARRAY:
-                    arr = new ArrayList<>();
-                    logger.debug("start array");
-                    break;
-                case END_ARRAY:
-                    // Check if just the end of array is entered
-                    if (result.keySet().size() == 0 && mapKey.equals("")) {
-                        return null;
-                    }
-                    result.put(mapKey, arr);
-                    arr = null;
-                    logger.debug("end array");
-                    break;
-                case VALUE_TRUE:
-                    if (arr == null) {
-                        result.put(mapKey, true);
-                    } else {
-                        arr.add(true);
-                    }
-                    logger.debug("value: true");
-                    break;
-                case VALUE_FALSE:
-                    if (arr == null) {
-                        result.put(mapKey, false);
-                    } else {
-                        arr.add(false);
-                    }
-                    logger.debug("value: false");
-                    break;
-                case VALUE_STRING:
-                    if (arr == null) {
-                        result.put(mapKey, jsonParser.getString());
-                    } else {
-                        arr.add(jsonParser.getString());
-                    }
-                    logger.debug("value string: " + jsonParser.getString());
-                    break;
-                case VALUE_NUMBER:
-                    if (arr == null) {
-                        result.put(mapKey, jsonParser.getBigDecimal());
-                    } else {
-                        arr.add(jsonParser.getBigDecimal());
-                    }
-                    logger.debug("value number: " + jsonParser.getBigDecimal());
-                    break;
-                case VALUE_NULL:
-                    logger.debug("value null");
-                    break;
-                default:
-                    logger.error("Error: " + event + " event is not handled in the JSON parser");
-                    break;
+                resultSchema.addEventProperty(p);
             }
-        }
 
-        return result;
+            return new AdapterGuessInfo(resultSchema, sample);
+        } catch (SpRuntimeException e) {
+            throw new ParseException("Could not serialize event, did you choose the correct format?", e);
+        }
     }
 }
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/util/JsonEventProperty.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/util/JsonEventProperty.java
index 6721638..a203190 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/util/JsonEventProperty.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/util/JsonEventProperty.java
@@ -55,7 +55,7 @@
             resultProperty = new EventPropertyPrimitive();
             resultProperty.setRuntimeName(key);
             ((EventPropertyPrimitive) resultProperty).setRuntimeType(XSD._string.toString());
-        } else if (o.getClass().equals(Integer.class) || o.getClass().equals(Double.class)|| o.getClass().equals(Long.class)) {
+        } else if (o.getClass().equals(Integer.class) || o.getClass().equals(Double.class) || o.getClass().equals(Float.class) || o.getClass().equals(Long.class)) {
             resultProperty = new EventPropertyPrimitive();
             resultProperty.setRuntimeName(key);
             ((EventPropertyPrimitive) resultProperty).setRuntimeType(XSD._float.toString());
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/guess/SchemaGuesser.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/guess/SchemaGuesser.java
index 53be8ab..29f534e 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/guess/SchemaGuesser.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/guess/SchemaGuesser.java
@@ -18,16 +18,24 @@
 
 package org.apache.streampipes.connect.adapter.guess;
 
+import org.apache.streampipes.model.connect.guess.AdapterGuessInfo;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
 import org.apache.streampipes.model.schema.EventSchema;
 
 public class SchemaGuesser {
 
-    public static GuessSchema guessSchma(EventSchema eventSchema) {
+    public static GuessSchema guessSchema(EventSchema eventSchema) {
         GuessSchema result = new GuessSchema();
 
         result.setEventSchema(eventSchema);
 
         return result;
     }
+
+    public static GuessSchema guessSchema(AdapterGuessInfo guessInfo) {
+        var result = guessSchema(guessInfo.getEventSchema());
+        result.setEventPreview(guessInfo.getEventPreview());
+
+        return result;
+    }
 }
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/model/pipeline/AdapterEventPreviewPipeline.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/model/pipeline/AdapterEventPreviewPipeline.java
new file mode 100644
index 0000000..3e36ad5
--- /dev/null
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/model/pipeline/AdapterEventPreviewPipeline.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.connect.adapter.model.pipeline;
+
+import org.apache.streampipes.connect.adapter.AdapterPipelineGenerator;
+import org.apache.streampipes.connect.api.IAdapterPipeline;
+import org.apache.streampipes.connect.api.IAdapterPipelineElement;
+import org.apache.streampipes.model.connect.guess.AdapterEventPreview;
+import org.apache.streampipes.model.connect.guess.GuessTypeInfo;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class AdapterEventPreviewPipeline implements IAdapterPipeline {
+
+  private List<IAdapterPipelineElement> pipelineElements;
+  private Map<String, GuessTypeInfo> event;
+
+  public AdapterEventPreviewPipeline(AdapterEventPreview previewRequest) {
+    this.pipelineElements = new AdapterPipelineGenerator().makeAdapterPipelineElements(previewRequest.getRules());
+    this.event = previewRequest.getInputData();
+  }
+
+  @Override
+  public void process(Map<String, Object> event) {
+    for (IAdapterPipelineElement pe : this.pipelineElements) {
+      event = pe.process(event);
+    }
+  }
+
+  @Override
+  public List<IAdapterPipelineElement> getPipelineElements() {
+    return null;
+  }
+
+  @Override
+  public void setPipelineElements(List<IAdapterPipelineElement> pipelineElements) {
+
+  }
+
+  @Override
+  public void changePipelineSink(IAdapterPipelineElement pipelineSink) {
+
+  }
+
+  @Override
+  public IAdapterPipelineElement getPipelineSink() {
+    return null;
+  }
+
+  public Map<String, GuessTypeInfo> makePreview() {
+    Map<String, Object> ev = this.event
+      .entrySet()
+      .stream()
+      .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getValue()));
+    this.process(ev);
+
+    return ev
+      .entrySet()
+      .stream()
+      .collect(Collectors.toMap(Map.Entry::getKey, e-> new GuessTypeInfo(e.getValue().getClass().getCanonicalName(), e.getValue())));
+  }
+}
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/elements/TransformSchemaAdapterPipelineElement.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/elements/TransformSchemaAdapterPipelineElement.java
index 735933f..e795af3 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/elements/TransformSchemaAdapterPipelineElement.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/elements/TransformSchemaAdapterPipelineElement.java
@@ -27,6 +27,7 @@
 import org.apache.streampipes.model.connect.rules.*;
 import org.apache.streampipes.model.connect.rules.schema.*;
 
+import javax.xml.crypto.dsig.Transform;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -36,7 +37,7 @@
     private SchemaEventTransformer eventTransformer;
     Logger logger = LoggerFactory.getLogger(TransformSchemaAdapterPipelineElement.class);
 
-    public TransformSchemaAdapterPipelineElement(List<SchemaTransformationRuleDescription> transformationRuleDescriptions) {
+    public TransformSchemaAdapterPipelineElement(List<? extends TransformationRuleDescription> transformationRuleDescriptions) {
         List<TransformationRule> rules = new ArrayList<>();
 
         // transforms description to actual rules
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/elements/TransformValueAdapterPipelineElement.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/elements/TransformValueAdapterPipelineElement.java
index 137966c..abb1bd2 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/elements/TransformValueAdapterPipelineElement.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/elements/TransformValueAdapterPipelineElement.java
@@ -18,16 +18,16 @@
 
 package org.apache.streampipes.connect.adapter.preprocessing.elements;
 
-import org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.streampipes.connect.api.IAdapterPipelineElement;
 import org.apache.streampipes.connect.adapter.preprocessing.Util;
 import org.apache.streampipes.connect.adapter.preprocessing.transform.value.*;
+import org.apache.streampipes.connect.api.IAdapterPipelineElement;
 import org.apache.streampipes.model.connect.rules.TransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription;
 import org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription;
 import org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription;
-import org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -35,20 +35,20 @@
 
 public class TransformValueAdapterPipelineElement implements IAdapterPipelineElement {
 
-    private ValueEventTransformer eventTransformer;
-    private Logger logger = LoggerFactory.getLogger(TransformValueAdapterPipelineElement.class);
+    private final ValueEventTransformer eventTransformer;
+    private final static Logger logger = LoggerFactory.getLogger(TransformValueAdapterPipelineElement.class);
 
-    public TransformValueAdapterPipelineElement(List<ValueTransformationRuleDescription> transformationRuleDescriptions) {
+    public TransformValueAdapterPipelineElement(List<? extends TransformationRuleDescription> transformationRuleDescriptions) {
         List<ValueTransformationRule> rules = new ArrayList<>();
 
         // transforms description to actual rules
         for (TransformationRuleDescription ruleDescription : transformationRuleDescriptions) {
             if (ruleDescription instanceof UnitTransformRuleDescription) {
-                UnitTransformRuleDescription tmp = (UnitTransformRuleDescription) ruleDescription;
+                var tmp = (UnitTransformRuleDescription) ruleDescription;
                 rules.add(new UnitTransformationRule(Util.toKeyArray(tmp.getRuntimeKey()),
                         tmp.getFromUnitRessourceURL(), tmp.getToUnitRessourceURL()));
-            } else if(ruleDescription instanceof TimestampTranfsformationRuleDescription) {
-                TimestampTranfsformationRuleDescription tmp = (TimestampTranfsformationRuleDescription) ruleDescription;
+            } else if (ruleDescription instanceof TimestampTranfsformationRuleDescription) {
+                var tmp = (TimestampTranfsformationRuleDescription) ruleDescription;
                 TimestampTranformationRuleMode mode = null;
                 switch (tmp.getMode()) {
                     case "formatString": mode = TimestampTranformationRuleMode.FORMAT_STRING;
@@ -58,9 +58,12 @@
                 rules.add(new TimestampTranformationRule(Util.toKeyArray(tmp.getRuntimeKey()), mode,
                         tmp.getFormatString(), tmp.getMultiplier()));
             }
-            else if(ruleDescription instanceof CorrectionValueTransformationRuleDescription) {
-                CorrectionValueTransformationRuleDescription tmp = (CorrectionValueTransformationRuleDescription) ruleDescription;
+            else if (ruleDescription instanceof CorrectionValueTransformationRuleDescription) {
+                var tmp = (CorrectionValueTransformationRuleDescription) ruleDescription;
                 rules.add(new CorrectionValueTransformationRule(Util.toKeyArray(tmp.getRuntimeKey()), tmp.getCorrectionValue(), tmp.getOperator()));
+            } else if (ruleDescription instanceof ChangeDatatypeTransformationRuleDescription) {
+                var tmp = (ChangeDatatypeTransformationRuleDescription) ruleDescription;
+                rules.add(new DatatypeTransformationRule(tmp.getRuntimeKey(), tmp.getOriginalDatatypeXsd(), tmp.getTargetDatatypeXsd()));
             }
 
             else {
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/transform/value/DatatypeTransformationRule.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/transform/value/DatatypeTransformationRule.java
new file mode 100644
index 0000000..d8c6d8a
--- /dev/null
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/transform/value/DatatypeTransformationRule.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.connect.adapter.preprocessing.transform.value;
+
+import org.apache.streampipes.connect.adapter.util.DatatypeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+public class DatatypeTransformationRule implements ValueTransformationRule {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DatatypeTransformationRule.class);
+
+  private String eventKey;
+  private String originalDatatypeXsd;
+  private String targetDatatypeXsd;
+
+  public DatatypeTransformationRule(String eventKey, String originalDatatypeXsd, String targetDatatypeXsd) {
+    this.eventKey = eventKey;
+    this.originalDatatypeXsd = originalDatatypeXsd;
+    this.targetDatatypeXsd = targetDatatypeXsd;
+  }
+
+  @Override
+  public Map<String, Object> transform(Map<String, Object> event) {
+    Object value = event.get(eventKey);
+    Object transformedValue = transformDatatype(value);
+    event.put(eventKey, transformedValue);
+    return event;
+  }
+
+  public Object transformDatatype(Object value) {
+    return DatatypeUtils.convertValue(value, targetDatatypeXsd);
+  }
+}
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/transform/value/ValueEventTransformer.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/transform/value/ValueEventTransformer.java
index 939cbad..c965c89 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/transform/value/ValueEventTransformer.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/preprocessing/transform/value/ValueEventTransformer.java
@@ -26,14 +26,16 @@
 
 public class ValueEventTransformer implements ValueTransformationRule {
 
-    private List<UnitTransformationRule> unitTransformationRules;
-    private List<TimestampTranformationRule> timestampTransformationRules;
-    private List<CorrectionValueTransformationRule> correctionValueTransformationRules;
+    private final List<UnitTransformationRule> unitTransformationRules;
+    private final List<TimestampTranformationRule> timestampTransformationRules;
+    private final List<CorrectionValueTransformationRule> correctionValueTransformationRules;
+    private final List<DatatypeTransformationRule> datatypeTransformationRules;
 
     public ValueEventTransformer(List<ValueTransformationRule> rules) {
         this.unitTransformationRules = new ArrayList<>();
         this.timestampTransformationRules = new ArrayList<>();
         this.correctionValueTransformationRules = new ArrayList<>();
+        this.datatypeTransformationRules = new ArrayList<>();
 
         for (TransformationRule rule : rules) {
             if (rule instanceof UnitTransformationRule) {
@@ -42,16 +44,12 @@
                 this.timestampTransformationRules.add((TimestampTranformationRule) rule);
             } else if (rule instanceof CorrectionValueTransformationRule) {
                 this.correctionValueTransformationRules.add((CorrectionValueTransformationRule) rule);
+            } else if (rule instanceof DatatypeTransformationRule) {
+                this.datatypeTransformationRules.add((DatatypeTransformationRule) rule);
             }
         }
     }
 
-/*
-    public ValueEventTransformer(List<UnitTransformationRule> unitTransformationRule) {
-        this.unitTransformationRules = new ArrayList<>();
-    }
-*/
-
     @Override
     public Map<String, Object> transform(Map<String, Object> event) {
 
@@ -63,36 +61,14 @@
             event = rule.transform(event);
         }
 
+        for (var rule: datatypeTransformationRules) {
+            event = rule.transform(event);
+        }
+
         for (CorrectionValueTransformationRule rule : correctionValueTransformationRules) {
             event = rule.transform(event);
         }
 
-
         return event;
     }
-
-
-    public List<UnitTransformationRule> getUnitTransformationRules() {
-        return unitTransformationRules;
-    }
-
-    public void setUnitTransformationRules(List<UnitTransformationRule> unitTransformationRules) {
-        this.unitTransformationRules = unitTransformationRules;
-    }
-
-    public List<TimestampTranformationRule> getTimestampTransformationRules() {
-        return timestampTransformationRules;
-    }
-
-    public void setTimestampTransformationRules(List<TimestampTranformationRule> timestampTransformationRules) {
-        this.timestampTransformationRules = timestampTransformationRules;
-    }
-
-    public List<CorrectionValueTransformationRule> getCorrectionValueTransformationRules() {
-        return correctionValueTransformationRules;
-    }
-
-    public void setCorrectionValueTransformationRules(List<CorrectionValueTransformationRule> correctionValueTransformationRules) {
-        this.correctionValueTransformationRules = correctionValueTransformationRules;
-    }
 }
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/util/DatatypeUtils.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/util/DatatypeUtils.java
new file mode 100644
index 0000000..f87bab3
--- /dev/null
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/util/DatatypeUtils.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.connect.adapter.util;
+
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.streampipes.vocabulary.XSD;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DatatypeUtils {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DatatypeUtils.class);
+
+  public static Object convertValue(Object value,
+                                    String targetDatatypeXsd) {
+    var stringValue = String.valueOf(value);
+    if (XSD._string.toString().equals(targetDatatypeXsd)) {
+      return stringValue;
+    } else {
+      try {
+        if (XSD._double.toString().equals(targetDatatypeXsd)) {
+          return Double.parseDouble(stringValue);
+        } else if (XSD._float.toString().equals(targetDatatypeXsd)) {
+          return Float.parseFloat(stringValue);
+        } else if (XSD._boolean.toString().equals(targetDatatypeXsd)) {
+          return Boolean.parseBoolean(stringValue);
+        } else if (XSD._integer.toString().equals(targetDatatypeXsd)) {
+          var floatingNumber = Float.parseFloat(stringValue);
+          return Integer.parseInt(String.valueOf(Math.round(floatingNumber)));
+        } else if (XSD._long.toString().equals(targetDatatypeXsd)) {
+          var floatingNumber = Double.parseDouble(stringValue);
+          return Long.parseLong(String.valueOf(Math.round(floatingNumber)));
+        }
+      } catch (NumberFormatException e) {
+        LOG.error("Number format exception {}", value);
+        return value;
+      }
+    }
+
+    return value;
+  }
+
+  public static String getCanonicalTypeClassName(String value,
+                                                 boolean preferFloat) {
+    return getTypeClass(value, preferFloat).getCanonicalName();
+  }
+
+  public static String getXsdDatatype(String value,
+                                      boolean preferFloat) {
+    var clazz = getTypeClass(value, preferFloat);
+    if (clazz.equals(Integer.class)) {
+      return XSD._integer.toString();
+    } else if (clazz.equals(Long.class)) {
+      return XSD._long.toString();
+    } else if (clazz.equals(Float.class)) {
+      return XSD._float.toString();
+    } else if (clazz.equals(Double.class)) {
+      return XSD._double.toString();
+    } else if (clazz.equals(Boolean.class)) {
+      return XSD._boolean.toString();
+    } else {
+      return XSD._string.toString();
+    }
+  }
+
+  public static Class<?> getTypeClass(String value,
+                                      boolean preferFloat) {
+    if (NumberUtils.isParsable(value)) {
+      try {
+        Integer.parseInt(value);
+        return preferFloat ? Float.class : Integer.class;
+      } catch (NumberFormatException ignored) {
+      }
+
+      try {
+        Long.parseLong(value);
+        return preferFloat ? Float.class : Long.class;
+      } catch (NumberFormatException ignored) {
+      }
+
+      try {
+        Double.parseDouble(value);
+        return Float.class;
+      } catch (NumberFormatException ignored) {
+      }
+
+    }
+
+    if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
+      return Boolean.class;
+    }
+
+    return String.class;
+  }
+
+  public static void main(String[] args) {
+    long max = Long.MAX_VALUE;
+    String className = getCanonicalTypeClassName(String.valueOf(max), true);
+    System.out.println(className);
+    System.out.println(convertValue(max, className));
+  }
+}
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/util/PollingSettings.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/util/PollingSettings.java
index 79dea5b..177702c 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/util/PollingSettings.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/util/PollingSettings.java
@@ -15,6 +15,7 @@
  * limitations under the License.
  *
  */
+
 package org.apache.streampipes.connect.adapter.util;
 
 import java.util.concurrent.TimeUnit;
diff --git a/streampipes-container-extensions/pom.xml b/streampipes-container-extensions/pom.xml
index 0166eb2..55c0192 100644
--- a/streampipes-container-extensions/pom.xml
+++ b/streampipes-container-extensions/pom.xml
@@ -17,13 +17,11 @@
   -->
 
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -34,17 +32,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect-container-worker</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-extensions-base</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-container-standalone/pom.xml b/streampipes-container-standalone/pom.xml
index b3ac21d..8bac498 100644
--- a/streampipes-container-standalone/pom.xml
+++ b/streampipes-container-standalone/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
        <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-extensions-base</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-container-standalone/src/main/java/org/apache/streampipes/container/standalone/init/StandaloneModelSubmitter.java b/streampipes-container-standalone/src/main/java/org/apache/streampipes/container/standalone/init/StandaloneModelSubmitter.java
index a23482c..037a6fb 100644
--- a/streampipes-container-standalone/src/main/java/org/apache/streampipes/container/standalone/init/StandaloneModelSubmitter.java
+++ b/streampipes-container-standalone/src/main/java/org/apache/streampipes/container/standalone/init/StandaloneModelSubmitter.java
@@ -24,6 +24,7 @@
 import org.apache.streampipes.container.model.PeConfig;
 import org.apache.streampipes.container.model.SpServiceDefinition;
 import org.apache.streampipes.service.extensions.base.StreamPipesExtensionsServiceBase;
+import org.apache.streampipes.service.extensions.base.WebSecurityConfig;
 import org.apache.streampipes.svcdiscovery.api.model.SpServiceTag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -37,7 +38,7 @@
 @Deprecated
 @Configuration
 @EnableAutoConfiguration
-@Import({ PipelineElementContainerResourceConfig.class })
+@Import({ PipelineElementContainerResourceConfig.class, WebSecurityConfig.class})
 public abstract class StandaloneModelSubmitter extends StreamPipesExtensionsServiceBase {
 
     private static final Logger LOG =
diff --git a/streampipes-container/pom.xml b/streampipes-container/pom.xml
index 5bc38c9..53bd31d 100644
--- a/streampipes-container/pom.xml
+++ b/streampipes-container/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<groupId>org.apache.streampipes</groupId>
 		<artifactId>streampipes-parent</artifactId>
-		<version>0.70.0-SNAPSHOT</version>
+		<version>0.71.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>streampipes-container</artifactId>
@@ -33,44 +33,38 @@
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-connect-api</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-dataformat</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-messaging</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-sdk</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-serializers-json</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-service-discovery</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-rest-shared</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
-<!--		<dependency>-->
-<!--			<groupId>org.apache.streampipes</groupId>-->
-<!--			<artifactId>streampipes-connect-container-worker</artifactId>-->
-<!--			<version>0.68.0-SNAPSHOT</version>-->
-<!--		</dependency>-->
-
 
 		<!-- External dependencies -->
 		<dependency>
diff --git a/streampipes-container/src/main/java/org/apache/streampipes/container/api/InvocablePipelineElementResource.java b/streampipes-container/src/main/java/org/apache/streampipes/container/api/InvocablePipelineElementResource.java
index 9936bd2..780b704 100644
--- a/streampipes-container/src/main/java/org/apache/streampipes/container/api/InvocablePipelineElementResource.java
+++ b/streampipes-container/src/main/java/org/apache/streampipes/container/api/InvocablePipelineElementResource.java
@@ -19,6 +19,7 @@
 package org.apache.streampipes.container.api;
 
 import org.apache.streampipes.commons.constants.Envs;
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.container.declarer.Declarer;
 import org.apache.streampipes.container.declarer.InvocableDeclarer;
@@ -106,14 +107,21 @@
     D declarer = getDeclarerById(elementId);
     RuntimeOptionsResponse responseOptions;
 
-    if (declarer instanceof ResolvesContainerProvidedOptions) {
-      responseOptions = new RuntimeResolvableRequestHandler().handleRuntimeResponse((ResolvesContainerProvidedOptions) declarer, req);
-      return ok(responseOptions);
-    } else if (declarer instanceof SupportsRuntimeConfig) {
-      responseOptions = new RuntimeResolvableRequestHandler().handleRuntimeResponse((SupportsRuntimeConfig) declarer, req);
-      return ok(responseOptions);
-    } else {
-      throw new WebApplicationException(javax.ws.rs.core.Response.Status.BAD_REQUEST);
+    try {
+      if (declarer instanceof ResolvesContainerProvidedOptions) {
+        responseOptions = new RuntimeResolvableRequestHandler().handleRuntimeResponse((ResolvesContainerProvidedOptions) declarer, req);
+        return ok(responseOptions);
+      } else if (declarer instanceof SupportsRuntimeConfig) {
+          responseOptions = new RuntimeResolvableRequestHandler().handleRuntimeResponse((SupportsRuntimeConfig) declarer, req);
+          return ok(responseOptions);
+      } else {
+        return javax.ws.rs.core.Response.status(500).build();
+      }
+    } catch (SpConfigurationException e) {
+      return javax.ws.rs.core.Response
+        .status(400)
+        .entity(e)
+        .build();
     }
   }
 
@@ -131,8 +139,7 @@
                               (elementId);
       return ok(resolvesOutput.resolveOutputStrategy
               (runtimeOptionsRequest, getExtractor(runtimeOptionsRequest)));
-    } catch (SpRuntimeException e) {
-      e.printStackTrace();
+    } catch (SpRuntimeException | SpConfigurationException e) {
       return ok(new Response(elementId, false));
     }
   }
diff --git a/streampipes-container/src/main/java/org/apache/streampipes/container/api/ResolvesContainerProvidedOptions.java b/streampipes-container/src/main/java/org/apache/streampipes/container/api/ResolvesContainerProvidedOptions.java
index a32a1de..110d95e 100644
--- a/streampipes-container/src/main/java/org/apache/streampipes/container/api/ResolvesContainerProvidedOptions.java
+++ b/streampipes-container/src/main/java/org/apache/streampipes/container/api/ResolvesContainerProvidedOptions.java
@@ -17,6 +17,7 @@
  */
 package org.apache.streampipes.container.api;
 
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.model.staticproperty.Option;
 import org.apache.streampipes.sdk.extractor.StaticPropertyExtractor;
 
@@ -29,5 +30,5 @@
 public interface ResolvesContainerProvidedOptions {
 
   List<Option> resolveOptions(String staticPropertyInternalName,
-                              StaticPropertyExtractor parameterExtractor);
+                              StaticPropertyExtractor parameterExtractor) throws SpConfigurationException;
 }
diff --git a/streampipes-container/src/main/java/org/apache/streampipes/container/api/ResolvesContainerProvidedOutputStrategy.java b/streampipes-container/src/main/java/org/apache/streampipes/container/api/ResolvesContainerProvidedOutputStrategy.java
index 83ed622..ab44539 100644
--- a/streampipes-container/src/main/java/org/apache/streampipes/container/api/ResolvesContainerProvidedOutputStrategy.java
+++ b/streampipes-container/src/main/java/org/apache/streampipes/container/api/ResolvesContainerProvidedOutputStrategy.java
@@ -17,7 +17,7 @@
  */
 package org.apache.streampipes.container.api;
 
-import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.model.base.InvocableStreamPipesEntity;
 import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.sdk.extractor.AbstractParameterExtractor;
@@ -25,5 +25,5 @@
 public interface ResolvesContainerProvidedOutputStrategy<T extends InvocableStreamPipesEntity, P
         extends AbstractParameterExtractor<T>> {
 
-  EventSchema resolveOutputStrategy(T processingElement, P parameterExtractor) throws SpRuntimeException;
+  EventSchema resolveOutputStrategy(T processingElement, P parameterExtractor) throws SpConfigurationException;
 }
diff --git a/streampipes-container/src/main/java/org/apache/streampipes/container/api/RuntimeResolvableRequestHandler.java b/streampipes-container/src/main/java/org/apache/streampipes/container/api/RuntimeResolvableRequestHandler.java
index aba1322..91e18f9 100644
--- a/streampipes-container/src/main/java/org/apache/streampipes/container/api/RuntimeResolvableRequestHandler.java
+++ b/streampipes-container/src/main/java/org/apache/streampipes/container/api/RuntimeResolvableRequestHandler.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.container.api;
 
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.model.runtime.RuntimeOptionsRequest;
 import org.apache.streampipes.model.runtime.RuntimeOptionsResponse;
 import org.apache.streampipes.model.staticproperty.Option;
@@ -31,7 +32,7 @@
 
   // for backwards compatibility
   public RuntimeOptionsResponse handleRuntimeResponse(ResolvesContainerProvidedOptions resolvesOptions,
-                                                      RuntimeOptionsRequest req) {
+                                                      RuntimeOptionsRequest req) throws SpConfigurationException {
     List<Option> availableOptions =
             resolvesOptions.resolveOptions(req.getRequestId(),
                     makeExtractor(req));
@@ -43,7 +44,7 @@
   }
 
   public RuntimeOptionsResponse handleRuntimeResponse(SupportsRuntimeConfig declarer,
-                                                      RuntimeOptionsRequest req) {
+                                                      RuntimeOptionsRequest req) throws SpConfigurationException {
     StaticProperty result = declarer.resolveConfiguration(
             req.getRequestId(),
             makeExtractor(req));
diff --git a/streampipes-container/src/main/java/org/apache/streampipes/container/api/SupportsRuntimeConfig.java b/streampipes-container/src/main/java/org/apache/streampipes/container/api/SupportsRuntimeConfig.java
index 10cacd1..4ebd768 100644
--- a/streampipes-container/src/main/java/org/apache/streampipes/container/api/SupportsRuntimeConfig.java
+++ b/streampipes-container/src/main/java/org/apache/streampipes/container/api/SupportsRuntimeConfig.java
@@ -18,12 +18,13 @@
 
 package org.apache.streampipes.container.api;
 
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.model.staticproperty.StaticProperty;
 import org.apache.streampipes.sdk.extractor.StaticPropertyExtractor;
 
 public interface SupportsRuntimeConfig {
 
   StaticProperty resolveConfiguration(String staticPropertyInternalName,
-                                      StaticPropertyExtractor extractor);
+                                      StaticPropertyExtractor extractor) throws SpConfigurationException;
 
 }
diff --git a/streampipes-container/src/main/java/org/apache/streampipes/container/model/SpServiceDefinitionBuilder.java b/streampipes-container/src/main/java/org/apache/streampipes/container/model/SpServiceDefinitionBuilder.java
index 3ad1308..0e0f290 100644
--- a/streampipes-container/src/main/java/org/apache/streampipes/container/model/SpServiceDefinitionBuilder.java
+++ b/streampipes-container/src/main/java/org/apache/streampipes/container/model/SpServiceDefinitionBuilder.java
@@ -28,6 +28,7 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.Arrays;
+import java.util.List;
 
 public class SpServiceDefinitionBuilder {
 
@@ -80,6 +81,11 @@
     return this;
   }
 
+  public SpServiceDefinitionBuilder addConfigs(List<ConfigItem> configItems) {
+    configItems.stream().forEach(configItem -> this.serviceDefinition.addConfig(configItem));
+    return this;
+  }
+
   public SpServiceDefinitionBuilder registerPipelineElement(Declarer<?> declarer) {
     this.serviceDefinition.addDeclarer(declarer);
     return this;
diff --git a/streampipes-data-explorer-commons/pom.xml b/streampipes-data-explorer-commons/pom.xml
new file mode 100644
index 0000000..c42e050
--- /dev/null
+++ b/streampipes-data-explorer-commons/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>streampipes-parent</artifactId>
+        <groupId>org.apache.streampipes</groupId>
+        <version>0.71.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>streampipes-data-explorer-commons</artifactId>
+    <dependencies>
+        <!-- StreamPipes -->
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-service-discovery-api</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-model</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-client</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-commons</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+
+
+        <!-- Others -->
+        <dependency>
+            <groupId>org.lightcouch</groupId>
+            <artifactId>lightcouch</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.influxdb</groupId>
+            <artifactId>influxdb-java</artifactId>
+        </dependency>
+    </dependencies>
+
+
+
+</project>
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/DataExplorerUtils.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/DataExplorerUtils.java
new file mode 100644
index 0000000..4fde783
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/DataExplorerUtils.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.dataexplorer.commons;
+
+import org.apache.streampipes.client.StreamPipesClient;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.dataexplorer.commons.influx.InfluxNameSanitizer;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.schema.EventProperty;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class DataExplorerUtils {
+    /**
+     * Sanitizes the event schema and stores the DataLakeMeasurement to the couchDB
+     *
+     * @param client StreamPipes client to store measure
+     * @param measure DataLakeMeasurement
+     */
+    public static DataLakeMeasure sanitizeAndRegisterAtDataLake(StreamPipesClient client,
+                                                     DataLakeMeasure measure) throws SpRuntimeException {
+        sanitizeDataLakeMeasure(measure);
+        registerAtDataLake(client, measure);
+
+        return measure;
+    }
+
+    private static void registerAtDataLake(StreamPipesClient client,
+                                                     DataLakeMeasure measure) throws SpRuntimeException {
+        client
+          .customRequest()
+          .sendPost("api/v4/datalake/measure/", measure);
+    }
+
+
+    private static void sanitizeDataLakeMeasure(DataLakeMeasure measure) throws SpRuntimeException {
+
+        // Removes selected timestamp from event schema
+        removeTimestampsFromEventSchema(measure);
+
+        // Removes all spaces with _ and validates that no special terms are used as runtime names
+        measure.getEventSchema()
+                .getEventProperties()
+                .forEach(ep -> ep.setRuntimeName(InfluxNameSanitizer.renameReservedKeywords(ep.getRuntimeName())));
+
+    }
+
+    private static void removeTimestampsFromEventSchema(DataLakeMeasure measure) {
+        List<EventProperty> eventPropertiesWithoutTimestamp = measure.getEventSchema().getEventProperties()
+          .stream()
+          .filter(eventProperty -> !measure.getTimestampField().endsWith(eventProperty.getRuntimeName()))
+          .collect(Collectors.toList());
+        measure.getEventSchema().setEventProperties(eventPropertiesWithoutTimestamp);
+    }
+
+}
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/DataExplorerWriter.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/DataExplorerWriter.java
new file mode 100644
index 0000000..925a08b
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/DataExplorerWriter.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons;
+
+import org.apache.streampipes.dataexplorer.commons.configs.DataExplorerConfigurations;
+import org.apache.streampipes.dataexplorer.commons.influx.InfluxConnectionSettings;
+import org.influxdb.InfluxDB;
+import org.influxdb.InfluxDBFactory;
+import org.influxdb.dto.Point;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Deprecated
+public class DataExplorerWriter {
+    private InfluxDB influxDB;
+
+    // TODO return a connection here
+    public void connect(InfluxConnectionSettings dataExplorerConnectionSettings) {
+        this.influxDB = InfluxDBFactory.connect(dataExplorerConnectionSettings.getInfluxDbHost() + ":" + dataExplorerConnectionSettings.getInfluxDbPort(),
+                dataExplorerConnectionSettings.getUser(), dataExplorerConnectionSettings.getPassword());
+        this.influxDB.setDatabase(DataExplorerConfigurations.DATA_LAKE_DATABASE_NAME);
+    }
+
+    public void close() {
+        this.influxDB.close();
+    }
+
+    public void write(Map<String, Object> data,
+                      String measurement) {
+        Point.Builder builder = Point.measurement(measurement)
+                .time((Long) data.get("timestamp"), TimeUnit.MILLISECONDS);
+
+        data.remove("timestamp");
+
+        for (String key : data.keySet()) {
+            if (data.get(key) instanceof Double || data.get(key) == null) {
+                builder.addField(key, (Double) data.get(key));
+            } else if (data.get(key) instanceof Integer) {
+                builder.addField(key, (Integer) data.get(key));
+            } else {
+                builder.tag(key, (String) data.get(key));
+            }
+        }
+
+        this.influxDB.write(builder.build());
+    }
+
+}
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/TimeSeriesStore.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/TimeSeriesStore.java
new file mode 100644
index 0000000..27fdcb3
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/TimeSeriesStore.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons;
+
+import org.apache.streampipes.client.StreamPipesClient;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.dataexplorer.commons.image.ImageStore;
+import org.apache.streampipes.dataexplorer.commons.influx.InfluxStore;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.svcdiscovery.api.SpConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+public class TimeSeriesStore {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TimeSeriesStore.class);
+
+    private ImageStore imageStore;
+    private final InfluxStore influxStore;
+
+
+    public TimeSeriesStore(SpConfig config,
+                           StreamPipesClient client,
+                           DataLakeMeasure measure,
+                           boolean enableImageStore) {
+
+        measure = DataExplorerUtils.sanitizeAndRegisterAtDataLake(client, measure);
+
+        if (enableImageStore) {
+            // TODO check if event properties are replaces correctly
+            this.imageStore = new ImageStore(measure, config);
+        }
+
+        this.influxStore = new InfluxStore(measure, config);
+
+    }
+
+    public boolean onEvent(Event event) throws SpRuntimeException {
+        // Store all images in image store and replace image with internal id
+        if (imageStore != null) {
+            this.imageStore.onEvent(event);
+        }
+
+        // Store event in time series database
+        this.influxStore.onEvent(event);
+
+        return true;
+    }
+
+
+    public boolean alterRetentionTime(DataLakeMeasure dataLakeMeasure) {
+        return true;
+    }
+
+    public void close() throws SpRuntimeException  {
+        if (imageStore != null) {
+            try {
+                this.imageStore.close();
+            } catch (IOException e) {
+                LOG.error("Could not close couchDB connection");
+                throw new SpRuntimeException(e);
+            }
+        }
+
+        this.influxStore.close();
+    }
+}
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/CouchDbConfigurations.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/CouchDbConfigurations.java
new file mode 100644
index 0000000..8079e9d
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/CouchDbConfigurations.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.dataexplorer.commons.configs;
+
+import org.apache.streampipes.svcdiscovery.api.model.ConfigItem;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class CouchDbConfigurations {
+
+    public static List<ConfigItem> getDefaults() {
+        return Arrays.asList(
+                ConfigItem.from(CouchDbEnvKeys.COUCHDB_HOST, "couchdb", "Hostname for CouchDB to store image blobs"),
+                ConfigItem.from(CouchDbEnvKeys.COUCHDB_PORT, 5984, ""),
+                ConfigItem.from(CouchDbEnvKeys.COUCHDB_PROTOCOL, "http", "")
+        );
+    }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/CouchDbEnvKeys.java
similarity index 72%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/CouchDbEnvKeys.java
index 58ba04b..69a5257 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/CouchDbEnvKeys.java
@@ -16,3 +16,10 @@
  *
  */
 
+package org.apache.streampipes.dataexplorer.commons.configs;
+
+public class CouchDbEnvKeys {
+    public final static String COUCHDB_HOST = "SP_COUCHDB_HOST";
+    public final static String COUCHDB_PORT = "SP_COUCHDB_PORT";
+    public final static String COUCHDB_PROTOCOL = "SP_COUCHDB_PROTOCOL";
+}
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/DataExplorerConfigurations.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/DataExplorerConfigurations.java
new file mode 100644
index 0000000..e0e483c
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/DataExplorerConfigurations.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.dataexplorer.commons.configs;
+
+import org.apache.streampipes.svcdiscovery.api.model.ConfigItem;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+public class DataExplorerConfigurations {
+    public final static String DATA_LAKE_DATABASE_NAME = "sp";
+
+    public static List<ConfigItem> getDefaults() {
+
+        return Arrays.asList(
+                ConfigItem.from(DataExplorerEnvKeys.DATA_LAKE_HOST, "influxdb", "Hostname for the StreamPipes data lake database"),
+                ConfigItem.from(DataExplorerEnvKeys.DATA_LAKE_PROTOCOL, "http", "Protocol for the StreamPipes data lake database"),
+                ConfigItem.from(DataExplorerEnvKeys.DATA_LAKE_PORT, 8086, "Port for the StreamPipes data lake database"),
+                ConfigItem.from(DataExplorerEnvKeys.DATA_LAKE_USERNAME, "default", "Username for the StreamPipes data lake database"),
+                ConfigItem.from(DataExplorerEnvKeys.DATA_LAKE_PASSWORD, "default", "Password for the StreamPipes data lake database"),
+                ConfigItem.from(DataExplorerEnvKeys.DATA_LAKE_DATABASE_NAME, DATA_LAKE_DATABASE_NAME, "Database name for the StreamPipes data lake database")
+        );
+    }
+
+}
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/config/ConfigKeys.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/DataExplorerEnvKeys.java
similarity index 80%
rename from streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/config/ConfigKeys.java
rename to streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/DataExplorerEnvKeys.java
index 4d6f0d9..cd4d17c 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/config/ConfigKeys.java
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/configs/DataExplorerEnvKeys.java
@@ -15,10 +15,9 @@
  * limitations under the License.
  *
  */
+package org.apache.streampipes.dataexplorer.commons.configs;
 
-package org.apache.streampipes.sinks.internal.jvm.config;
-
-public class ConfigKeys {
+public class DataExplorerEnvKeys {
     public final static String DATA_LAKE_HOST = "SP_DATA_LAKE_HOST";
     public final static String DATA_LAKE_PROTOCOL = "SP_DATA_LAKE_PROTOCOL";
     public final static String DATA_LAKE_PORT = "SP_DATA_LAKE_PORT";
@@ -26,7 +25,4 @@
     public final static String DATA_LAKE_PASSWORD = "SP_DATA_LAKE_PASSWORD";
     public final static String DATA_LAKE_DATABASE_NAME = "SP_DATA_LAKE_DATABASE_NAME";
 
-    public final static String COUCHDB_HOST = "SP_COUCHDB_HOST";
-    public final static String COUCHDB_PORT = "SP_COUCHDB_PORT";
-    public final static String COUCHDB_PROTOCOL = "SP_COUCHDB_PROTOCOL";
 }
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/image/ImageStore.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/image/ImageStore.java
new file mode 100644
index 0000000..21c51c2
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/image/ImageStore.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons.image;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.dataexplorer.commons.configs.CouchDbEnvKeys;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.svcdiscovery.api.SpConfig;
+import org.lightcouch.CouchDbClient;
+import org.lightcouch.CouchDbProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.UUID;
+
+public class ImageStore {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ImageStore.class);
+  private static final String DB_NAME = "images";
+
+  private List<EventProperty> imageProperties;
+  private CouchDbClient couchDbClient;
+
+  public ImageStore(DataLakeMeasure measure, SpConfig config) {
+    this.couchDbClient = new CouchDbClient(from(config));
+    this.imageProperties = ImageStoreUtils.getImageProperties(measure);
+  }
+
+  public void onEvent(Event event) throws SpRuntimeException{
+    this.imageProperties.forEach(eventProperty -> {
+      String imageDocId = UUID.randomUUID().toString();
+      String image = event.getFieldByRuntimeName(eventProperty.getRuntimeName()).getAsPrimitive().getAsString();
+
+      byte[] data = Base64.decodeBase64(image);
+      storeImage(data, imageDocId);
+      event.updateFieldBySelector("s0::" + eventProperty.getRuntimeName(), imageDocId);
+    });
+  }
+
+  public void storeImage(byte[] imageBytes,
+                         String imageDocId) {
+    this.couchDbClient.saveAttachment(
+      new ByteArrayInputStream(imageBytes),
+      imageDocId,
+      "image/jpeg",
+      imageDocId,
+      null);
+
+  }
+
+  public void close() throws IOException {
+    this.couchDbClient.close();
+  }
+
+  private static CouchDbProperties from(SpConfig config) {
+    String couchDbProtocol = config.getString(CouchDbEnvKeys.COUCHDB_PROTOCOL);
+    String couchDbHost = config.getString(CouchDbEnvKeys.COUCHDB_HOST);
+    int couchDbPort = config.getInteger(CouchDbEnvKeys.COUCHDB_PORT);
+
+    return new CouchDbProperties(DB_NAME, true, couchDbProtocol,
+      couchDbHost, couchDbPort, null, null);
+  }
+}
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/image/ImageStoreUtils.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/image/ImageStoreUtils.java
new file mode 100644
index 0000000..ba3ab6c
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/image/ImageStoreUtils.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons.image;
+
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.vocabulary.SPSensor;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ImageStoreUtils {
+
+    public static List<EventProperty> getImageProperties(DataLakeMeasure measure) {
+        return  measure.getEventSchema().getEventProperties().stream()
+                .filter(eventProperty -> eventProperty.getDomainProperties() != null &&
+            eventProperty.getDomainProperties().size() > 0 &&
+            eventProperty.getDomainProperties().get(0).toString().equals(SPSensor.IMAGE))
+            .collect(Collectors.toList());
+    }
+}
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxConnectionSettings.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxConnectionSettings.java
new file mode 100644
index 0000000..a6c1538
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxConnectionSettings.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons.influx;
+
+import org.apache.streampipes.dataexplorer.commons.configs.DataExplorerEnvKeys;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.svcdiscovery.api.SpConfig;
+
+public class InfluxConnectionSettings {
+
+  private final Integer influxDbPort;
+  private final String influxDbHost;
+  private final String databaseName;
+  private final String user;
+  private final String password;
+
+  public static InfluxConnectionSettings from(SpConfig configStore) {
+
+    return new InfluxConnectionSettings(
+            configStore.getString(DataExplorerEnvKeys.DATA_LAKE_PROTOCOL) + "://" + configStore.getString(DataExplorerEnvKeys.DATA_LAKE_HOST),
+            configStore.getInteger(DataExplorerEnvKeys.DATA_LAKE_PORT),
+            configStore.getString(DataExplorerEnvKeys.DATA_LAKE_DATABASE_NAME),
+            configStore.getString(DataExplorerEnvKeys.DATA_LAKE_USERNAME),
+            configStore.getString(DataExplorerEnvKeys.DATA_LAKE_PASSWORD));
+  }
+
+
+  private InfluxConnectionSettings(String influxDbHost,
+                                   Integer influxDbPort,
+                                   String databaseName,
+                                   String user,
+                                   String password) {
+    this.influxDbHost = influxDbHost;
+    this.influxDbPort = influxDbPort;
+    this.databaseName = databaseName;
+    this.user = user;
+    this.password = password;
+  }
+
+  public Integer getInfluxDbPort() {
+    return influxDbPort;
+  }
+
+  public String getInfluxDbHost() {
+    return influxDbHost;
+  }
+
+  public String getDatabaseName() {
+    return databaseName;
+  }
+
+  public String getUser() {
+    return user;
+  }
+
+  public String getPassword() {
+    return password;
+  }
+}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/InfluxDbReservedKeywords.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxDbReservedKeywords.java
similarity index 97%
rename from streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/InfluxDbReservedKeywords.java
rename to streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxDbReservedKeywords.java
index 26e7a14..754fc7c 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/InfluxDbReservedKeywords.java
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxDbReservedKeywords.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.sinks.internal.jvm.datalake;
+package org.apache.streampipes.dataexplorer.commons.influx;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationDivide.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxNameSanitizer.java
similarity index 68%
copy from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationDivide.java
copy to streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxNameSanitizer.java
index b648a20..302ea45 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationDivide.java
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxNameSanitizer.java
@@ -16,12 +16,16 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.math.operation;
+package org.apache.streampipes.dataexplorer.commons.influx;
 
-public class OperationDivide implements Operation {
+public class InfluxNameSanitizer {
 
-    @Override
-    public Double operate(Double valLeft, Double valRight) {
-        return valLeft / valRight;
+    public static String renameReservedKeywords(String runtimeName) {
+        if (InfluxDbReservedKeywords.keywordList.stream().anyMatch(k -> k.equalsIgnoreCase(runtimeName))) {
+            return runtimeName + "_";
+        } else {
+            return runtimeName;
+        }
     }
+
 }
diff --git a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStore.java b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStore.java
new file mode 100644
index 0000000..429f62e
--- /dev/null
+++ b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStore.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons.influx;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.runtime.field.PrimitiveField;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.svcdiscovery.api.SpConfig;
+import org.apache.streampipes.vocabulary.XSD;
+import org.influxdb.InfluxDB;
+import org.influxdb.InfluxDBFactory;
+import org.influxdb.dto.Point;
+import org.influxdb.dto.Pong;
+import org.influxdb.dto.Query;
+import org.influxdb.dto.QueryResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class InfluxStore {
+
+  private static final Logger LOG = LoggerFactory.getLogger(InfluxStore.class);
+
+  private InfluxDB influxDb = null;
+  DataLakeMeasure measure;
+
+  Map<String, String> sanitizedRuntimeNames = new HashMap<>();
+
+  public InfluxStore(DataLakeMeasure measure,
+                     SpConfig configStore) throws SpRuntimeException {
+
+    this.measure = measure;
+    InfluxConnectionSettings settings = InfluxConnectionSettings.from(configStore);
+
+    // store sanitized target property runtime names in local variable
+    measure.getEventSchema()
+        .getEventProperties()
+        .forEach(ep -> sanitizedRuntimeNames.put(ep.getRuntimeName(),
+            InfluxNameSanitizer.renameReservedKeywords(ep.getRuntimeName())));
+
+    connect(settings);
+  }
+
+  /**
+   * Connects to the InfluxDB Server, sets the database and initializes the batch-behaviour
+   *
+   * @throws SpRuntimeException If not connection can be established or if the database could not
+   *                            be found
+   */
+  private void connect(InfluxConnectionSettings settings) throws SpRuntimeException {
+    // Connecting to the server
+    // "http://" must be in front
+    String urlAndPort = settings.getInfluxDbHost() + ":" + settings.getInfluxDbPort();
+    influxDb = InfluxDBFactory.connect(urlAndPort, settings.getUser(), settings.getPassword());
+
+    // Checking, if server is available
+    Pong response = influxDb.ping();
+    if (response.getVersion().equalsIgnoreCase("unknown")) {
+      throw new SpRuntimeException("Could not connect to InfluxDb Server: " + urlAndPort);
+    }
+
+    String databaseName = settings.getDatabaseName();
+    // Checking whether the database exists
+    if (!databaseExists(databaseName)) {
+      LOG.info("Database '" + databaseName + "' not found. Gets created ...");
+      createDatabase(databaseName);
+    }
+
+    // setting up the database
+    influxDb.setDatabase(databaseName);
+    int batchSize = 2000;
+    int flushDuration = 500;
+    influxDb.enableBatch(batchSize, flushDuration, TimeUnit.MILLISECONDS);
+  }
+
+  private boolean databaseExists(String dbName) {
+    QueryResult queryResult = influxDb.query(new Query("SHOW DATABASES", ""));
+    for (List<Object> a : queryResult.getResults().get(0).getSeries().get(0).getValues()) {
+      if (a.get(0).equals(dbName)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Creates a new database with the given name
+   *
+   * @param dbName The name of the database which should be created
+   */
+  private void createDatabase(String dbName) throws SpRuntimeException {
+    if (!dbName.matches("^[a-zA-Z_]\\w*$")) {
+      throw new SpRuntimeException(
+          "Database name '" + dbName + "' not allowed. Allowed names: ^[a-zA-Z_][a-zA-Z0-9_]*$");
+    }
+    influxDb.query(new Query("CREATE DATABASE \"" + dbName + "\"", ""));
+  }
+
+  /**
+   * Saves an event to the connected InfluxDB database
+   *
+   * @param event The event which should be saved
+   * @throws SpRuntimeException If the column name (key-value of the event map) is not allowed
+   */
+  public void onEvent(Event event) throws SpRuntimeException {
+    if (event == null) {
+      throw new SpRuntimeException("event is null");
+    }
+
+    Long timestampValue = event.getFieldBySelector(measure.getTimestampField()).getAsPrimitive().getAsLong();
+    Point.Builder point =
+        Point.measurement(measure.getMeasureName()).time((long) timestampValue, TimeUnit.MILLISECONDS);
+
+    for (EventProperty ep : measure.getEventSchema().getEventProperties()) {
+      if (ep instanceof EventPropertyPrimitive) {
+        String runtimeName = ep.getRuntimeName();
+
+        // timestamp should not be added as a field
+        if (!measure.getTimestampField().endsWith(runtimeName)) {
+          String sanitizedRuntimeName = sanitizedRuntimeNames.get(runtimeName);
+
+          try {
+            PrimitiveField eventPropertyPrimitiveField = event.getFieldByRuntimeName(runtimeName).getAsPrimitive();
+            if (eventPropertyPrimitiveField.getRawValue() == null) {
+              LOG.warn("Field value for {} is null, ignoring value.", sanitizedRuntimeName);
+            } else {
+
+              // store property as tag when the field is a dimension property
+              if (PropertyScope.DIMENSION_PROPERTY.name().equals(ep.getPropertyScope())) {
+                point.tag(sanitizedRuntimeName, eventPropertyPrimitiveField.getAsString());
+              } else {
+                handleMeasurementProperty(
+                    point,
+                    (EventPropertyPrimitive) ep,
+                    sanitizedRuntimeName,
+                    eventPropertyPrimitiveField);
+              }
+            }
+          } catch (SpRuntimeException iae) {
+            LOG.warn("Field {} was missing in event and will be ignored", runtimeName, iae);
+          }
+
+        }
+
+      }
+    }
+
+    influxDb.write(point.build());
+  }
+
+  private void handleMeasurementProperty(Point.Builder p,
+                                         EventPropertyPrimitive ep,
+                                         String preparedRuntimeName,
+                                         PrimitiveField eventPropertyPrimitiveField) {
+    try {
+      // Store property according to property type
+      String runtimeType = ep.getRuntimeType();
+      if (XSD._integer.toString().equals(runtimeType)) {
+        try {
+          p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsInt());
+        } catch (NumberFormatException ef) {
+          p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsFloat());
+        }
+      } else if (XSD._float.toString().equals(runtimeType)) {
+        p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsFloat());
+      } else if (XSD._double.toString().equals(runtimeType)) {
+        p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsDouble());
+      } else if (XSD._boolean.toString().equals(runtimeType)) {
+        p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsBoolean());
+      } else if (XSD._long.toString().equals(runtimeType)) {
+        try {
+          p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsLong());
+        } catch (NumberFormatException ef) {
+          p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsFloat());
+        }
+      } else {
+        p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsString());
+      }
+    } catch (NumberFormatException e) {
+      LOG.warn("Wrong number format for field {}, ignoring.", preparedRuntimeName);
+    }
+  }
+
+  /**
+   * Shuts down the connection to the InfluxDB server
+   */
+  public void close() throws SpRuntimeException {
+    influxDb.flush();
+    try {
+      Thread.sleep(1000);
+    } catch (InterruptedException e) {
+      throw new SpRuntimeException(e);
+    }
+    influxDb.close();
+  }
+
+}
diff --git a/streampipes-data-explorer/pom.xml b/streampipes-data-explorer/pom.xml
index 4079bfe..78d1676 100644
--- a/streampipes-data-explorer/pom.xml
+++ b/streampipes-data-explorer/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -31,17 +31,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <dependency>
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeManagementV4.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeManagementV4.java
index b5c68df..f9918fc 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeManagementV4.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeManagementV4.java
@@ -36,7 +36,13 @@
 import org.apache.streampipes.model.datalake.DataLakeMeasure;
 import org.apache.streampipes.model.datalake.DataLakeRetentionPolicy;
 import org.apache.streampipes.model.datalake.SpQueryResult;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyList;
+import org.apache.streampipes.model.schema.EventPropertyNested;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.storage.api.IDataLakeStorage;
 import org.apache.streampipes.storage.couchdb.utils.Utils;
+import org.apache.streampipes.storage.management.StorageDispatcher;
 import org.influxdb.InfluxDB;
 import org.influxdb.dto.Query;
 import org.influxdb.dto.QueryResult;
@@ -53,16 +59,15 @@
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalAccessor;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static org.apache.streampipes.dataexplorer.v4.SupportedDataLakeQueryParameters.*;
 
 public class DataLakeManagementV4 {
 
+    public static final String FOR_ID_KEY = "forId";
+
     private static final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
             .appendPattern("uuuu[-MM[-dd]]['T'HH[:mm[:ss[.SSSSSSSSS][.SSSSSSSS][.SSSSSSS][.SSSSSS][.SSSSS][.SSSS][.SSS][.SS][.S]]]][XXX]")
             .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
@@ -73,6 +78,10 @@
         return DataExplorerUtils.getInfos();
     }
 
+    public DataLakeMeasure getById(String measureId) {
+        return getDataLakeStorage().findOne(measureId);
+    }
+
     public SpQueryResult getData(ProvidedQueryParams queryParams) throws IllegalArgumentException {
         if (queryParams.has(QP_AUTO_AGGREGATE)) {
             queryParams = new AutoAggregationHandler(queryParams).makeAutoAggregationQueryParams();
@@ -84,7 +93,12 @@
             return new DataExplorerQueryV4(queryParts, maximumAmountOfEvents).executeQuery();
         }
 
-        return new DataExplorerQueryV4(queryParts).executeQuery();
+        if (queryParams.getProvidedParams().containsKey(FOR_ID_KEY)) {
+            String forWidgetId = queryParams.getProvidedParams().get(FOR_ID_KEY);
+            return new DataExplorerQueryV4(queryParts, forWidgetId).executeQuery();
+        } else {
+            return new DataExplorerQueryV4(queryParts).executeQuery();
+        }
     }
 
     public void getDataAsStream(ProvidedQueryParams params, String format, OutputStream outputStream) throws IOException {
@@ -148,6 +162,11 @@
             }
 
             boolean isFirstDataObject = true;
+            String delimiter = ",";
+
+            if (params.has(QP_CSV_DELIMITER)) {
+                delimiter = params.getAsString(QP_CSV_DELIMITER).equals("comma") ? "," : ";";
+            }
 
             do {
                 params.update(SupportedDataLakeQueryParameters.QP_PAGE, String.valueOf(i));
@@ -158,7 +177,7 @@
                         boolean isFirst = true;
                         for (int i1 = 0; i1 < dataResult.getHeaders().size(); i1++) {
                             if (!isFirst) {
-                                outputStream.write(toBytes(";"));
+                                outputStream.write(toBytes(delimiter));
                             }
                             isFirst = false;
                             outputStream.write(toBytes(dataResult.getHeaders().get(i1)));
@@ -174,7 +193,7 @@
                         for (int i1 = 0; i1 < row.size(); i1++) {
                             Object element = row.get(i1);
                             if (!isFirstInRow) {
-                                outputStream.write(toBytes(";"));
+                                outputStream.write(toBytes(delimiter));
                             }
                             isFirstInRow = false;
                             if (i1 == 0) {
@@ -307,9 +326,10 @@
                                             String fields) {
         InfluxDB influxDB = DataExplorerUtils.getInfluxDBClient();
         Map<String, Object> tags = new HashMap<>();
-        List<String> fieldList = Arrays.asList(fields.split(","));
-        fieldList.forEach(f -> {
-                String q = "SHOW TAG VALUES ON \"" + BackendConfig.INSTANCE.getInfluxDatabaseName() + "\" FROM \"" +measurementId + "\" WITH KEY = \"" +f + "\"";
+        if (fields != null && !("".equals(fields))) {
+            List<String> fieldList = Arrays.asList(fields.split(","));
+            fieldList.forEach(f -> {
+                String q = "SHOW TAG VALUES ON \"" + BackendConfig.INSTANCE.getInfluxDatabaseName() + "\" FROM \"" + measurementId + "\" WITH KEY = \"" + f + "\"";
                 Query query = new Query(q);
                 QueryResult queryResult = influxDB.query(query);
                 if (queryResult.getResults() != null) {
@@ -323,8 +343,69 @@
                         });
                     });
                 }
-        });
+            });
+        }
 
         return tags;
     }
+
+
+    // TODO validate method
+    public DataLakeMeasure addDataLake(DataLakeMeasure measure) {
+        List<DataLakeMeasure> dataLakeMeasureList = getDataLakeStorage().getAllDataLakeMeasures();
+        Optional<DataLakeMeasure> optional = dataLakeMeasureList.stream().filter(entry -> entry.getMeasureName().equals(measure.getMeasureName())).findFirst();
+
+        if (optional.isPresent()) {
+            DataLakeMeasure oldEntry = optional.get();
+            if (!compareEventProperties(oldEntry.getEventSchema().getEventProperties(), measure.getEventSchema().getEventProperties())) {
+                return oldEntry;
+            }
+        } else {
+            measure.setSchemaVersion(DataLakeMeasure.CURRENT_SCHEMA_VERSION);
+            getDataLakeStorage().storeDataLakeMeasure(measure);
+            return measure;
+        }
+
+        return measure;
+    }
+
+    private boolean compareEventProperties(List<EventProperty> prop1, List<EventProperty> prop2) {
+        if (prop1.size() != prop2.size()) {
+            return false;
+        }
+
+        return prop1.stream().allMatch(prop -> {
+
+            for (EventProperty property : prop2) {
+                if (prop.getRuntimeName().equals(property.getRuntimeName())) {
+
+                    //primitive
+                    if (prop instanceof EventPropertyPrimitive && property instanceof EventPropertyPrimitive) {
+                        if (((EventPropertyPrimitive) prop)
+                          .getRuntimeType()
+                          .equals(((EventPropertyPrimitive) property).getRuntimeType())) {
+                            return true;
+                        }
+
+                        //list
+                    } else if (prop instanceof EventPropertyList && property instanceof EventPropertyList) {
+                        return compareEventProperties(Collections.singletonList(((EventPropertyList) prop).getEventProperty()),
+                          Collections.singletonList(((EventPropertyList) property).getEventProperty()));
+
+                        //nested
+                    } else if (prop instanceof EventPropertyNested && property instanceof EventPropertyNested) {
+                        return compareEventProperties(((EventPropertyNested) prop).getEventProperties(),
+                          ((EventPropertyNested) property).getEventProperties());
+                    }
+                }
+            }
+            return false;
+
+        });
+    }
+
+
+    private IDataLakeStorage getDataLakeStorage() {
+        return StorageDispatcher.INSTANCE.getNoSqlStore().getDataLakeStorage();
+    }
 }
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeNoUserManagementV3.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeNoUserManagementV3.java
index 3f9c7bd..5b411a0 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeNoUserManagementV3.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeNoUserManagementV3.java
@@ -28,8 +28,11 @@
 import java.util.Optional;
 
 
+@Deprecated
 public class DataLakeNoUserManagementV3 {
 
+
+  @Deprecated
   public boolean addDataLake(String measure, EventSchema eventSchema) {
     List<DataLakeMeasure> dataLakeMeasureList = getDataLakeStorage().getAllDataLakeMeasures();
     Optional<DataLakeMeasure> optional = dataLakeMeasureList.stream().filter(entry -> entry.getMeasureName().equals(measure)).findFirst();
@@ -39,7 +42,9 @@
         return false;
       }
     } else {
-      getDataLakeStorage().storeDataLakeMeasure(new DataLakeMeasure(measure, eventSchema));
+      DataLakeMeasure dataLakeMeasure = new DataLakeMeasure(measure, eventSchema);
+      dataLakeMeasure.setSchemaVersion(DataLakeMeasure.CURRENT_SCHEMA_VERSION);
+      getDataLakeStorage().storeDataLakeMeasure(dataLakeMeasure);
     }
     return true;
   }
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/query/DeleteDataQuery.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/query/DeleteDataQuery.java
index 73d6be6..4570927 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/query/DeleteDataQuery.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/query/DeleteDataQuery.java
@@ -30,7 +30,7 @@
 
   @Override
   protected void getQuery(DataExplorerQueryBuilder queryBuilder) {
-    queryBuilder.add("DROP MEASUREMENT " + measure.getMeasureName());
+    queryBuilder.add("DROP MEASUREMENT \"" + measure.getMeasureName() + "\"");
   }
 
   @Override
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryBuilder.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryBuilder.java
new file mode 100644
index 0000000..b4ea310
--- /dev/null
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryBuilder.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.sdk;
+
+import org.apache.streampipes.config.backend.BackendConfig;
+import org.apache.streampipes.dataexplorer.v4.params.ColumnFunction;
+import org.influxdb.dto.Query;
+import org.influxdb.querybuilder.Ordering;
+import org.influxdb.querybuilder.SelectionQueryImpl;
+import org.influxdb.querybuilder.clauses.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.*;
+
+public class DataLakeQueryBuilder {
+
+  private final String measurementId;
+  private final SelectionQueryImpl selectionQuery;
+  private final List<Clause> whereClauses;
+  private final List<Clause> groupByClauses;
+  private Ordering ordering;
+  private int limit = Integer.MIN_VALUE;
+
+  public static DataLakeQueryBuilder create(String measurementId) {
+    return new DataLakeQueryBuilder(measurementId);
+  }
+
+  private DataLakeQueryBuilder(String measurementId) {
+    this.measurementId = measurementId;
+    this.selectionQuery = select();
+    this.whereClauses = new ArrayList<>();
+    this.groupByClauses = new ArrayList<>();
+  }
+
+  public DataLakeQueryBuilder withSimpleColumn(String columnName) {
+    this.selectionQuery.column(columnName);
+
+    return this;
+  }
+
+  public DataLakeQueryBuilder withAggregatedColumn(String columnName,
+                                                   ColumnFunction columnFunction,
+                                                   String targetName) {
+    if (columnFunction == ColumnFunction.COUNT) {
+      this.selectionQuery.count(columnName).as(targetName);
+    } else if (columnFunction == ColumnFunction.MEAN) {
+      this.selectionQuery.mean(columnName).as(targetName);
+    } else if (columnFunction == ColumnFunction.MIN) {
+      this.selectionQuery.min(columnName).as(targetName);
+    } else if (columnFunction == ColumnFunction.MAX) {
+      this.selectionQuery.max(columnName).as(targetName);
+    } else if (columnFunction == ColumnFunction.FIRST) {
+      this.selectionQuery.function("FIRST", columnName).as(targetName);
+    } else if (columnFunction == ColumnFunction.LAST) {
+      this.selectionQuery.function("LAST", columnName).as(targetName);
+    }
+
+    // TODO implement all column functions
+
+    return this;
+  }
+
+  public DataLakeQueryBuilder withStartTime(long startTime) {
+    this.whereClauses.add(new SimpleClause("time", ">=", startTime * 1000000));
+    return this;
+  }
+
+
+  public DataLakeQueryBuilder withEndTime(long endTime) {
+    return withEndTime(endTime, true);
+  }
+
+  public DataLakeQueryBuilder withEndTime(long endTime,
+                                          boolean includeEndTime) {
+    String operator = includeEndTime ? "<=" : "<";
+    this.whereClauses.add(new SimpleClause("time", operator, endTime * 1000000));
+    return this;
+  }
+
+  public DataLakeQueryBuilder withTimeBoundary(long startTime,
+                                               long endTime) {
+    this.withStartTime(startTime);
+    this.withEndTime(endTime);
+
+    return this;
+  }
+
+  public DataLakeQueryBuilder withFilter(String field,
+                                         String operator,
+                                         Object value) {
+    this.whereClauses.add(new SimpleClause(field, operator, value));
+    return this;
+  }
+
+  public DataLakeQueryBuilder withExclusiveFilter(String field,
+                                                  String operator,
+                                                  List<?> values) {
+    List<ConjunctionClause> or = new ArrayList<>();
+    values.forEach(value -> {
+      or.add(new OrConjunction(new SimpleClause(field, operator, value)));
+    });
+
+    NestedClause nestedClause = new NestedClause(or);
+    this.whereClauses.add(nestedClause);
+
+    return this;
+  }
+
+  public DataLakeQueryBuilder withFilter(NestedClause clause) {
+    this.whereClauses.add(clause);
+
+    return this;
+  }
+
+  public DataLakeQueryBuilder withGroupByTime(String timeInterval) {
+
+    this.groupByClauses.add(new RawTextClause("time(" + timeInterval + ")"));
+
+    return this;
+  }
+
+  public DataLakeQueryBuilder withGroupBy(String column) {
+
+    this.groupByClauses.add(new RawTextClause(column));
+
+    return this;
+  }
+
+  public DataLakeQueryBuilder withOrderBy(DataLakeQueryOrdering ordering) {
+    if (DataLakeQueryOrdering.ASC.equals(ordering)) {
+      this.ordering =  asc();
+    } else {
+      this.ordering =  desc();
+    }
+
+    return this;
+  }
+
+  public DataLakeQueryBuilder withLimit(int limit) {
+    this.limit = limit;
+
+    return this;
+  }
+
+  public Query build() {
+    var selectQuery = this.selectionQuery.from(BackendConfig.INSTANCE.getInfluxDatabaseName(), "\"" +measurementId + "\"");
+    this.whereClauses.forEach(selectQuery::where);
+
+    if (this.groupByClauses.size() > 0) {
+      selectQuery.groupBy(this.groupByClauses.toArray());
+    }
+
+    if (this.ordering != null) {
+     selectQuery.orderBy(this.ordering);
+    }
+
+    if (this.limit != Integer.MIN_VALUE) {
+      selectQuery.limit(this.limit);
+    }
+
+    return selectQuery;
+  }
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryConstants.java
similarity index 70%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryConstants.java
index 58ba04b..f6664f4 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryConstants.java
@@ -16,3 +16,15 @@
  *
  */
 
+package org.apache.streampipes.dataexplorer.sdk;
+
+public class DataLakeQueryConstants {
+
+  public static final String GE = ">=";
+  public static final String LE = "<=";
+  public static final String LT = "<";
+  public static final String GT = ">";
+  public static final String EQ = "=";
+  public static final String NEQ = "!=";
+
+}
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryOrdering.java
similarity index 88%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryOrdering.java
index a375af7..6952d0d 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/sdk/DataLakeQueryOrdering.java
@@ -16,7 +16,8 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
-}
+package org.apache.streampipes.dataexplorer.sdk;
 
+public enum DataLakeQueryOrdering {
+    ASC, DESC
+}
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/SupportedDataLakeQueryParameters.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/SupportedDataLakeQueryParameters.java
index 3a08624..1eadd81 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/SupportedDataLakeQueryParameters.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/SupportedDataLakeQueryParameters.java
@@ -33,6 +33,7 @@
   public static final String QP_AGGREGATION_FUNCTION = "aggregationFunction";
   public static final String QP_TIME_INTERVAL = "timeInterval";
   public static final String QP_FORMAT = "format";
+  public static final String QP_CSV_DELIMITER = "delimiter";
   public static final String QP_COUNT_ONLY = "countOnly";
   public static final String QP_AUTO_AGGREGATE = "autoAggregate";
   public static final String QP_FILTER = "filter";
@@ -50,6 +51,7 @@
           QP_AGGREGATION_FUNCTION,
           QP_TIME_INTERVAL,
           QP_FORMAT,
+          QP_CSV_DELIMITER,
           QP_COUNT_ONLY,
           QP_AUTO_AGGREGATE,
           QP_FILTER,
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/params/SelectColumn.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/params/SelectColumn.java
index 3b2a5f4..d2d0ba9 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/params/SelectColumn.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/params/SelectColumn.java
@@ -71,16 +71,16 @@
 
   private String makeField() {
     if (this.simpleField) {
-      return this.originalField;
+      return "\"" + this.originalField + "\"";
     } else {
-      return this.columnFunction.toDbName() + "(" + this.originalField + ")";
+      return this.columnFunction.toDbName() + "(\"" + this.originalField + "\")";
     }
   }
 
   public String toQueryString() {
     String field = makeField();
     if (this.rename) {
-      return field + " AS " + this.targetField;
+      return field + " AS \"" + this.targetField + "\"";
     } else {
       return field;
     }
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/params/WhereStatementParams.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/params/WhereStatementParams.java
index e3dbd84..a0af420 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/params/WhereStatementParams.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/params/WhereStatementParams.java
@@ -103,6 +103,8 @@
   private String returnCondition(String inputCondition) {
     if (NumberUtils.isCreatable(inputCondition) || Boolean.parseBoolean(inputCondition)) {
       return inputCondition;
+    } else if (inputCondition.equals("\"\"")) {
+      return inputCondition;
     } else {
       return "'" + inputCondition + "'";
     }
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/query/DataExplorerQueryV4.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/query/DataExplorerQueryV4.java
index c1a5121..30a87d4 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/query/DataExplorerQueryV4.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/query/DataExplorerQueryV4.java
@@ -44,6 +44,20 @@
 
     protected int maximumAmountOfEvents;
 
+    private boolean appendId = false;
+    private String forId;
+
+    public DataExplorerQueryV4() {
+
+    }
+
+    public DataExplorerQueryV4(Map<String, QueryParamsV4> params,
+                               String forId) {
+        this(params);
+        this.appendId = true;
+        this.forId = forId;
+    }
+
     public DataExplorerQueryV4(Map<String, QueryParamsV4> params) {
         this.params = params;
         this.maximumAmountOfEvents = -1;
@@ -61,7 +75,8 @@
         if (this.maximumAmountOfEvents != -1) {
             QueryBuilder countQueryBuilder = QueryBuilder.create(BackendConfig.INSTANCE.getInfluxDatabaseName());
             Query countQuery = countQueryBuilder.build(queryElements, true);
-            Double amountOfQueryResults = getAmountOfResults(influxDB.query(countQuery));
+            QueryResult countQueryResult = influxDB.query(countQuery);
+            Double amountOfQueryResults = getAmountOfResults(countQueryResult);
             if (amountOfQueryResults > this.maximumAmountOfEvents) {
                 SpQueryResult tooMuchData = new SpQueryResult();
                 tooMuchData.setSpQueryStatus(SpQueryStatus.TOO_MUCH_DATA);
@@ -84,6 +99,15 @@
         return dataResult;
     }
 
+    public SpQueryResult executeQuery(Query query) {
+        InfluxDB influxDB = DataExplorerUtils.getInfluxDBClient();
+        QueryResult result = influxDB.query(query);
+        SpQueryResult dataResult = postQuery(result);
+        influxDB.close();
+
+        return dataResult;
+    }
+
     private double getAmountOfResults(QueryResult countQueryResult) {
         if (countQueryResult.getResults().get(0).getSeries() != null &&
                 countQueryResult.getResults().get(0).getSeries().get(0).getValues() != null) {
@@ -120,6 +144,11 @@
                 result.addDataResult(series);
             });
         }
+
+        if (this.appendId) {
+            result.setForId(this.forId);
+        }
+
         return result;
     }
 
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/query/elements/SelectFromStatement.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/query/elements/SelectFromStatement.java
index 731d348..9630367 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/query/elements/SelectFromStatement.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/query/elements/SelectFromStatement.java
@@ -23,6 +23,7 @@
 import java.util.StringJoiner;
 
 public class SelectFromStatement extends QueryElement<SelectFromStatementParams> {
+
   public SelectFromStatement(SelectFromStatementParams selectFromStatementParams) {
     super(selectFromStatementParams);
   }
@@ -30,11 +31,11 @@
   @Override
   protected String buildStatement(SelectFromStatementParams params) {
     if (params.isSelectWildcard()) {
-      return "SELECT * FROM " + params.getIndex();
+      return "SELECT * FROM " + escapeIndex(params.getIndex());
     } else {
       StringJoiner joiner = new StringJoiner(",");
       String queryPrefix = "SELECT ";
-      String queryAppendix = " FROM " +params.getIndex();
+      String queryAppendix = " FROM " +escapeIndex(params.getIndex());
 
       params.getSelectedColumns().forEach(column -> {
         joiner.add(column.toQueryString());
@@ -42,12 +43,9 @@
 
       return queryPrefix + joiner + queryAppendix;
     }
-//        if (selectFromStatementParams.isCountOnly()) {
-//            return QueryTemplatesV4.selectCountFrom(selectFromStatementParams.getIndex(), selectFromStatementParams.getSelectedColumns());
-//        } else if (selectFromStatementParams.getAggregationFunction() == null) {
-//            return QueryTemplatesV4.selectFrom(selectFromStatementParams.getIndex(), selectFromStatementParams.getSelectedColumns());
-//        } else {
-//            return QueryTemplatesV4.selectAggregationFrom(selectFromStatementParams.getIndex(), selectFromStatementParams.getSelectedColumns(), selectFromStatementParams.getAggregationFunction());
-//        }
+  }
+
+  private String escapeIndex(String index) {
+    return "\"" + index + "\"";
   }
 }
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/template/QueryTemplatesV4.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/template/QueryTemplatesV4.java
index 0023cc2..dd681d6 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/template/QueryTemplatesV4.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/v4/template/QueryTemplatesV4.java
@@ -42,11 +42,11 @@
             joiner.add(builder);
         }
 
-        return "SELECT " + joiner + " FROM " + index;
+        return "SELECT " + joiner + " FROM \"" + index + "\"";
     }
 
     public static String deleteFrom(String index) {
-        return "DELETE FROM " + index;
+        return "DELETE FROM \"" + index + "\"";
     }
 
     public static String whereTimeWithin(long startDate, long endDate) {
diff --git a/streampipes-data-export/pom.xml b/streampipes-data-export/pom.xml
new file mode 100644
index 0000000..8dc44bf
--- /dev/null
+++ b/streampipes-data-export/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>streampipes-parent</artifactId>
+        <groupId>org.apache.streampipes</groupId>
+        <version>0.71.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>streampipes-data-export</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-model</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-pipeline-management</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-resource-management</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-storage-management</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/AssetLinkCollector.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/AssetLinkCollector.java
new file mode 100644
index 0000000..ba3e16d
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/AssetLinkCollector.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export;
+
+import org.apache.streampipes.model.assets.AssetLink;
+import org.apache.streampipes.model.assets.SpAsset;
+import org.apache.streampipes.model.assets.SpAssetModel;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class AssetLinkCollector {
+
+  private SpAssetModel assetModel;
+
+  public AssetLinkCollector(SpAssetModel assetModel) {
+    this.assetModel = assetModel;
+  }
+
+  public Set<AssetLink> collectAssetLinks() {
+    var assetLinks = new HashSet<>(assetModel.getAssetLinks());
+    assetModel.getAssets().forEach(asset -> addLinks(assetLinks, asset));
+
+    return assetLinks;
+  }
+
+  private void addLinks(HashSet<AssetLink> assetLinks,
+                        SpAsset asset) {
+    assetLinks.addAll(asset.getAssetLinks());
+    if (asset.getAssets() != null) {
+      asset.getAssets().forEach(a -> addLinks(assetLinks, a));
+    }
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/AssetLinkResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/AssetLinkResolver.java
new file mode 100644
index 0000000..fb24122
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/AssetLinkResolver.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.streampipes.export.constants.ResolvableAssetLinks;
+import org.apache.streampipes.export.resolver.*;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.assets.AssetLink;
+import org.apache.streampipes.model.assets.SpAssetModel;
+import org.apache.streampipes.model.export.AssetExportConfiguration;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class AssetLinkResolver {
+
+  private final String assetId;
+  private final ObjectMapper mapper;
+
+  public AssetLinkResolver(String assetId) {
+    this.assetId = assetId;
+    this.mapper = SerializationUtils.getDefaultObjectMapper();
+  }
+
+  public AssetExportConfiguration resolveResources() {
+
+    try {
+      var asset = getAsset();
+      var assetLinks = new AssetLinkCollector(asset).collectAssetLinks();
+      var exportConfig = new AssetExportConfiguration();
+      exportConfig.setAssetId(this.assetId);
+      exportConfig.setAssetName(asset.getAssetName());
+      exportConfig.setAdapters(new AdapterResolver().resolve(getLinks(assetLinks, ResolvableAssetLinks.ADAPTER)));
+      exportConfig.setDashboards(new DashboardResolver().resolve(getLinks(assetLinks, ResolvableAssetLinks.DASHBOARD)));
+      exportConfig.setDataViews(new DataViewResolver().resolve(getLinks(assetLinks, ResolvableAssetLinks.DATA_VIEW)));
+      exportConfig.setDataSources(new DataSourceResolver().resolve(getLinks(assetLinks, ResolvableAssetLinks.DATA_SOURCE)));
+      exportConfig.setPipelines(new PipelineResolver().resolve(getLinks(assetLinks, ResolvableAssetLinks.PIPELINE)));
+      exportConfig.setDataLakeMeasures(new MeasurementResolver().resolve(getLinks(assetLinks, ResolvableAssetLinks.MEASUREMENT)));
+      exportConfig.setFiles(new FileResolver().resolve(getLinks(assetLinks, ResolvableAssetLinks.FILE)));
+
+      return exportConfig;
+    } catch (IOException e) {
+      e.printStackTrace();
+      return new AssetExportConfiguration();
+    }
+  }
+
+  private Set<AssetLink> getLinks(Set<AssetLink> assetLinks,
+                                  String queryHint) {
+    return assetLinks
+      .stream()
+      .filter(link -> link.getQueryHint().equals(queryHint))
+      .collect(Collectors.toSet());
+  }
+
+  private SpAssetModel getAsset() throws IOException {
+    return deserialize(StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().findOne(this.assetId));
+  }
+
+  private SpAssetModel deserialize(Map<String, Object> asset) {
+    return this.mapper.convertValue(asset, SpAssetModel.class);
+  }
+
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/ExportManager.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/ExportManager.java
new file mode 100644
index 0000000..1ceaa54
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/ExportManager.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export;
+
+import org.apache.streampipes.export.generator.ExportPackageGenerator;
+import org.apache.streampipes.model.export.ExportConfiguration;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ExportManager {
+  
+  public static ExportConfiguration getExportPreview(List<String> selectedAssetIds) {
+    var exportConfig = new ExportConfiguration();
+    var assetExportConfigurations = selectedAssetIds
+      .stream()
+      .map(assetId -> new AssetLinkResolver(assetId).resolveResources())
+      .collect(Collectors.toList());
+
+    exportConfig.setAssetExportConfiguration(assetExportConfigurations);
+
+    return exportConfig;
+  }
+
+  public static byte[] getExportPackage(ExportConfiguration exportConfiguration) throws IOException {
+    return new ExportPackageGenerator(exportConfiguration).generateExportPackage();
+  }
+
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/ImportManager.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/ImportManager.java
new file mode 100644
index 0000000..58bfe95
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/ImportManager.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export;
+
+import org.apache.streampipes.export.dataimport.PerformImportGenerator;
+import org.apache.streampipes.export.dataimport.PreviewImportGenerator;
+import org.apache.streampipes.model.export.AssetExportConfiguration;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ImportManager {
+
+  public static AssetExportConfiguration getImportPreview(InputStream packageZipStream) throws IOException {
+    return new PreviewImportGenerator().generate(packageZipStream);
+  }
+
+  public static void performImport(InputStream packageZipStream,
+                                   AssetExportConfiguration exportConfiguration,
+                                   String ownerSid) throws IOException {
+    new PerformImportGenerator(exportConfiguration, ownerSid).generate(packageZipStream);
+  }
+}
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/streampipes-data-export/src/main/java/org/apache/streampipes/export/constants/ExportConstants.java
similarity index 85%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to streampipes-data-export/src/main/java/org/apache/streampipes/export/constants/ExportConstants.java
index a375af7..80ec171 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/constants/ExportConstants.java
@@ -16,7 +16,9 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
-}
+package org.apache.streampipes.export.constants;
 
+public class ExportConstants {
+
+  public static final String MANIFEST = "manifest";
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-data-export/src/main/java/org/apache/streampipes/export/constants/ResolvableAssetLinks.java
similarity index 63%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-data-export/src/main/java/org/apache/streampipes/export/constants/ResolvableAssetLinks.java
index 58ba04b..35588da 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/constants/ResolvableAssetLinks.java
@@ -16,3 +16,15 @@
  *
  */
 
+package org.apache.streampipes.export.constants;
+
+public class ResolvableAssetLinks {
+
+  public static final String DATA_VIEW = "data-view";
+  public static final String DASHBOARD = "dashboard";
+  public static final String MEASUREMENT = "measurement";
+  public static final String ADAPTER = "adapter";
+  public static final String DATA_SOURCE = "data-source";
+  public static final String PIPELINE = "pipeline";
+  public static final String FILE = "file";
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/ImportGenerator.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/ImportGenerator.java
new file mode 100644
index 0000000..23bd41d
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/ImportGenerator.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.dataimport;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.streampipes.commons.zip.ZipFileExtractor;
+import org.apache.streampipes.export.constants.ExportConstants;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.export.StreamPipesApplicationPackage;
+import org.lightcouch.DocumentConflictException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+public abstract class ImportGenerator<T> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ImportGenerator.class);
+
+  protected ObjectMapper spMapper;
+  protected ObjectMapper defaultMapper;
+
+  public ImportGenerator() {
+    this.spMapper = SerializationUtils.getSpObjectMapper();
+    this.defaultMapper = SerializationUtils.getDefaultObjectMapper();
+  }
+
+  public T generate(InputStream inputStream) throws IOException {
+    Map<String, byte[]> previewFiles = new ZipFileExtractor(inputStream).extractZipToMap();
+
+    var manifest = getManifest(previewFiles);
+
+    for (String assetId : manifest.getAssets()) {
+      try {
+        handleAsset(previewFiles, assetId);
+      } catch (DocumentConflictException | IOException e) {
+        LOG.warn("Skipping import of asset model {} (already present with the same id)", assetId);
+      }
+    }
+
+    for (String adapterId : manifest.getAdapters()) {
+      try {
+        handleAdapter(asString(previewFiles.get(adapterId)), adapterId);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of adapter {} (already present with the same id)", adapterId);
+      }
+    }
+
+    for (String dashboardId : manifest.getDashboards()) {
+      try {
+      handleDashboard(asString(previewFiles.get(dashboardId)), dashboardId);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of dashboard {} (already present with the same id)", dashboardId);
+      }
+    }
+
+    for (String dataViewId : manifest.getDataViews()) {
+      try {
+      handleDataView(asString(previewFiles.get(dataViewId)), dataViewId);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of data view {} (already present with the same id)", dataViewId);
+      }
+    }
+
+    for (String dataSourceId : manifest.getDataSources()) {
+      try {
+      handleDataSource(asString(previewFiles.get(dataSourceId)), dataSourceId);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of data source {} (already present with the same id)", dataSourceId);
+      }
+    }
+
+    for (String pipelineId : manifest.getPipelines()) {
+      try {
+      handlePipeline(asString(previewFiles.get(pipelineId)), pipelineId);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of pipeline {} (already present with the same id)", pipelineId);
+      }
+    }
+
+    for (String measurementId : manifest.getDataLakeMeasures()) {
+      try {
+      handleDataLakeMeasure(asString(previewFiles.get(measurementId)), measurementId);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of data lake measure {} (already present with the same id)", measurementId);
+      }
+    }
+
+    for (String dashboardWidgetId : manifest.getDashboardWidgets()) {
+      try {
+      handleDashboardWidget(asString(previewFiles.get(dashboardWidgetId)), dashboardWidgetId);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of dashboard widget {} (already present with the same id)", dashboardWidgetId);
+      }
+    }
+
+    for (String dataViewWidgetId : manifest.getDataViewWidgets()) {
+      try {
+      handleDataViewWidget(asString(previewFiles.get(dataViewWidgetId)), dataViewWidgetId);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of data view widget {} (already present with the same id)", dataViewWidgetId);
+      }
+    }
+
+    for (String fileMetadataId : manifest.getFiles()) {
+      try {
+      handleFile(asString(previewFiles.get(fileMetadataId)), fileMetadataId, previewFiles);
+      } catch (DocumentConflictException e) {
+        LOG.warn("Skipping import of file {} (already present with the same id)", fileMetadataId);
+      }
+    }
+
+    afterResourcesCreated();
+
+    return getReturnObject();
+  }
+
+  protected String asString(byte[] bytes) {
+    return new String(bytes, StandardCharsets.UTF_8);
+  }
+
+  private StreamPipesApplicationPackage getManifest(Map<String, byte[]> previewFiles) throws JsonProcessingException {
+    return this.defaultMapper.readValue(asString(previewFiles.get(ExportConstants.MANIFEST)), StreamPipesApplicationPackage.class);
+  }
+
+  protected abstract void handleAsset(Map<String, byte[]> previewFiles, String assetId) throws IOException;
+
+  protected abstract void handleAdapter(String document, String adapterId) throws JsonProcessingException;
+
+  protected abstract void handleDashboard(String document, String dashboardId) throws JsonProcessingException;
+
+  protected abstract void handleDataView(String document, String dataViewId) throws JsonProcessingException;
+
+  protected abstract void handleDataSource(String document, String dataSourceId) throws JsonProcessingException;
+
+  protected abstract void handlePipeline(String document, String pipelineId) throws JsonProcessingException;
+
+  protected abstract void handleDataLakeMeasure(String document, String dataLakeMeasureId) throws JsonProcessingException;
+
+  protected abstract void handleDashboardWidget(String document, String dashboardWidgetId) throws JsonProcessingException;
+
+  protected abstract void handleDataViewWidget(String document, String dataViewWidgetId) throws JsonProcessingException;
+
+  protected abstract void handleFile(String document, String fileMetadataId, Map<String, byte[]> zipContent) throws IOException;
+
+  protected abstract T getReturnObject();
+
+  protected abstract void afterResourcesCreated();
+
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/PerformImportGenerator.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/PerformImportGenerator.java
new file mode 100644
index 0000000..f4345f9
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/PerformImportGenerator.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.dataimport;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.model.PermissionInfo;
+import org.apache.streampipes.export.resolver.*;
+import org.apache.streampipes.manager.file.FileHandler;
+import org.apache.streampipes.model.SpDataStream;
+import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import org.apache.streampipes.model.dashboard.DashboardModel;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.export.AssetExportConfiguration;
+import org.apache.streampipes.model.export.ExportItem;
+import org.apache.streampipes.model.pipeline.Pipeline;
+import org.apache.streampipes.resource.management.PermissionResourceManager;
+import org.apache.streampipes.storage.api.INoSqlStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class PerformImportGenerator extends ImportGenerator<Void> {
+
+  private AssetExportConfiguration config;
+  private INoSqlStorage storage;
+  private Set<PermissionInfo> permissionsToStore = new HashSet<>();
+  private String ownerSid;
+
+  public PerformImportGenerator(AssetExportConfiguration config,
+                                String ownerSid) {
+    this.config = config;
+    this.storage = StorageDispatcher.INSTANCE.getNoSqlStore();
+    this.ownerSid = ownerSid;
+  }
+
+  @Override
+  protected void handleAsset(Map<String, byte[]> previewFiles, String assetId) throws IOException {
+    storage.getGenericStorage().create(asString(previewFiles.get(assetId)));
+  }
+
+  @Override
+  protected void handleAdapter(String document, String adapterId) throws JsonProcessingException {
+    if (shouldStore(adapterId, config.getAdapters())) {
+      new AdapterResolver().writeDocument(document, config.isOverrideBrokerSettings());
+      permissionsToStore.add(new PermissionInfo(adapterId, AdapterDescription.class));
+    }
+  }
+
+  @Override
+  protected void handleDashboard(String document, String dashboardId) throws JsonProcessingException {
+    if (shouldStore(dashboardId, config.getDashboards())) {
+      new DashboardResolver().writeDocument(document);
+      permissionsToStore.add(new PermissionInfo(dashboardId, DashboardModel.class));
+    }
+  }
+
+  @Override
+  protected void handleDataView(String document, String dataViewId) throws JsonProcessingException {
+    if (shouldStore(dataViewId, config.getDataViews())) {
+      new DataViewResolver().writeDocument(document);
+      permissionsToStore.add(new PermissionInfo(dataViewId, DashboardModel.class));
+    }
+  }
+
+  @Override
+  protected void handleDataSource(String document, String dataSourceId) throws JsonProcessingException {
+    if (shouldStore(dataSourceId, config.getDataSources())) {
+      new DataSourceResolver().writeDocument(document, config.isOverrideBrokerSettings());
+      permissionsToStore.add(new PermissionInfo(dataSourceId, SpDataStream.class));
+    }
+  }
+
+  @Override
+  protected void handlePipeline(String document, String pipelineId) throws JsonProcessingException {
+    if (shouldStore(pipelineId, config.getPipelines())) {
+      new PipelineResolver().writeDocument(document, config.isOverrideBrokerSettings());
+      permissionsToStore.add(new PermissionInfo(pipelineId, Pipeline.class));
+    }
+  }
+
+  @Override
+  protected void handleDataLakeMeasure(String document, String dataLakeMeasureId) throws JsonProcessingException {
+    if (shouldStore(dataLakeMeasureId, config.getDataLakeMeasures())) {
+      new MeasurementResolver().writeDocument(document);
+      permissionsToStore.add(new PermissionInfo(dataLakeMeasureId, DataLakeMeasure.class));
+    }
+  }
+
+  @Override
+  protected void handleDashboardWidget(String document, String dashboardWidgetId) throws JsonProcessingException {
+    new DashboardWidgetResolver().writeDocument(document);
+  }
+
+  @Override
+  protected void handleDataViewWidget(String document, String dataViewWidget) throws JsonProcessingException {
+    new DataViewWidgetResolver().writeDocument(document);
+  }
+
+  @Override
+  protected void handleFile(String document,
+                            String fileMetadataId,
+                            Map<String, byte[]> zipContent) throws IOException {
+    var resolver = new FileResolver();
+    var fileMetadata = resolver.readDocument(document);
+    resolver.writeDocument(document);
+    byte[] file = zipContent.get(fileMetadata.getInternalFilename().substring(0, fileMetadata.getInternalFilename().lastIndexOf(".")));
+    new FileHandler().storeFile(fileMetadata.getInternalFilename(), new ByteArrayInputStream(file));
+  }
+
+  @Override
+  protected Void getReturnObject() {
+    return null;
+  }
+
+  @Override
+  protected void afterResourcesCreated() {
+    var resourceManager = new PermissionResourceManager();
+    this.permissionsToStore
+      .forEach(info -> resourceManager.createDefault(
+        info.getInstanceId(),
+        info.getInstanceClass(),
+        this.ownerSid,
+        true));
+  }
+
+  private boolean shouldStore(String adapterId,
+                              Set<ExportItem> adapters) {
+    return adapters
+      .stream()
+      .filter(item -> item.getResourceId().equals(adapterId))
+      .allMatch(ExportItem::isSelected);
+  }
+
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/PreviewImportGenerator.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/PreviewImportGenerator.java
new file mode 100644
index 0000000..80c4894
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/dataimport/PreviewImportGenerator.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.dataimport;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import org.apache.streampipes.export.resolver.*;
+import org.apache.streampipes.model.export.AssetExportConfiguration;
+import org.apache.streampipes.model.export.ExportItem;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+public class PreviewImportGenerator extends ImportGenerator<AssetExportConfiguration> {
+
+  private AssetExportConfiguration importConfig;
+
+  public PreviewImportGenerator() {
+    super();
+    this.importConfig = new AssetExportConfiguration();
+
+  }
+
+  private void addExportItem(String id,
+                             String name,
+                             Consumer<ExportItem> addAdapter) {
+    var item = new ExportItem(id, name, true);
+    addAdapter.accept(item);
+  }
+
+
+  @Override
+  protected void handleAsset(Map<String, byte[]> previewFiles, String assetId) throws JsonProcessingException {
+    Map<String, Object> assetDescription = this.defaultMapper.readValue(asString(previewFiles.get(assetId)), new TypeReference<Map<String, Object>>() {});
+    importConfig.addAsset(new ExportItem(assetId, String.valueOf(assetDescription.get("assetName")), true));
+  }
+
+  @Override
+  protected void handleAdapter(String document, String adapterId) throws JsonProcessingException {
+    addExportItem(adapterId, new AdapterResolver().readDocument(document).getName(), importConfig::addAdapter);
+  }
+
+  @Override
+  protected void handleDashboard(String document, String dashboardId) throws JsonProcessingException {
+    addExportItem(dashboardId, new DashboardResolver().readDocument(document).getName(), importConfig::addDashboard);
+  }
+
+  @Override
+  protected void handleDataView(String document, String dataViewId) throws JsonProcessingException {
+    addExportItem(dataViewId, new DataViewResolver().readDocument(document).getName(), importConfig::addDataView);
+  }
+
+  @Override
+  protected void handleDataSource(String document, String dataSourceId) throws JsonProcessingException {
+    addExportItem(dataSourceId, new DataSourceResolver().readDocument(document).getName(), importConfig::addDataSource);
+  }
+
+  @Override
+  protected void handlePipeline(String document, String pipelineId) throws JsonProcessingException {
+    addExportItem(pipelineId, new PipelineResolver().readDocument(document).getName(), importConfig::addPipeline);
+  }
+
+  @Override
+  protected void handleDataLakeMeasure(String document, String measurementId) throws JsonProcessingException {
+    addExportItem(measurementId, new MeasurementResolver().readDocument(document).getMeasureName(), importConfig::addDataLakeMeasure);
+  }
+
+  @Override
+  protected void handleDashboardWidget(String document, String dashboardWidgetId) {
+
+  }
+
+  @Override
+  protected void handleDataViewWidget(String document, String dataViewWidget) {
+
+  }
+
+  @Override
+  protected void handleFile(String document,
+                            String fileMetadataId,
+                            Map<String, byte[]> zipContent) throws JsonProcessingException {
+    addExportItem(fileMetadataId, new FileResolver().readDocument(document).getOriginalFilename(), importConfig::addFile);
+  }
+
+  @Override
+  protected AssetExportConfiguration getReturnObject() {
+    return this.importConfig;
+  }
+
+  @Override
+  protected void afterResourcesCreated() {
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/generator/ExportPackageGenerator.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/generator/ExportPackageGenerator.java
new file mode 100644
index 0000000..8073dd5
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/generator/ExportPackageGenerator.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.generator;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.streampipes.commons.exceptions.ElementNotFoundException;
+import org.apache.streampipes.export.resolver.*;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.manager.file.FileManager;
+import org.apache.streampipes.model.export.AssetExportConfiguration;
+import org.apache.streampipes.model.export.ExportConfiguration;
+import org.apache.streampipes.model.export.ExportItem;
+import org.apache.streampipes.model.export.StreamPipesApplicationPackage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+public class ExportPackageGenerator {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ExportPackageGenerator.class);
+
+  private final ExportConfiguration exportConfiguration;
+  private ObjectMapper defaultMapper;
+  private ObjectMapper spMapper;
+
+  public ExportPackageGenerator(ExportConfiguration exportConfiguration) {
+    this.exportConfiguration = exportConfiguration;
+    this.defaultMapper = SerializationUtils.getDefaultObjectMapper();
+    this.spMapper = SerializationUtils.getSpObjectMapper();
+  }
+
+  public byte[] generateExportPackage() throws IOException {
+    ZipFileBuilder builder = ZipFileBuilder.create();
+    var manifest = new StreamPipesApplicationPackage();
+
+    addAssets(builder, exportConfiguration
+      .getAssetExportConfiguration()
+      .stream()
+      .map(AssetExportConfiguration::getAssetId)
+      .collect(Collectors.toList()), manifest);
+
+    this.exportConfiguration.getAssetExportConfiguration().forEach(config -> {
+
+      config.getAdapters().forEach(item -> addDoc(builder,
+        item,
+        new AdapterResolver(),
+        manifest::addAdapter));
+
+      config.getDashboards().forEach(item -> {
+        var resolver = new DashboardResolver();
+        addDoc(builder,
+          item,
+          resolver,
+          manifest::addDashboard);
+
+        var widgets = resolver.getWidgets(item.getResourceId());
+        var widgetResolver = new DashboardWidgetResolver();
+        widgets.forEach(widgetId -> addDoc(builder, widgetId, widgetResolver, manifest::addDashboardWidget));
+      });
+
+      config.getDataSources().forEach(item -> addDoc(builder,
+        item,
+        new DataSourceResolver(),
+        manifest::addDataSource));
+
+      config.getDataLakeMeasures().forEach(item -> addDoc(builder,
+        item,
+        new MeasurementResolver(),
+        manifest::addDataLakeMeasure));
+
+      config.getPipelines().forEach(item -> addDoc(builder,
+        item,
+        new PipelineResolver(),
+        manifest::addPipeline));
+
+      config.getDataViews().forEach(item -> {
+        var resolver = new DataViewResolver();
+        addDoc(builder,
+          item,
+          resolver,
+          manifest::addDataView);
+
+        var widgets = resolver.getWidgets(item.getResourceId());
+        var widgetResolver = new DataViewWidgetResolver();
+        widgets.forEach(widgetId -> addDoc(builder, widgetId, widgetResolver, manifest::addDataViewWidget));
+      });
+
+      config.getFiles().forEach(item -> {
+        var fileResolver = new FileResolver();
+        String filename = fileResolver.findDocument(item.getResourceId()).getInternalFilename();
+        addDoc(builder, item, new FileResolver(), manifest::addFile);
+        try {
+          builder.addBinary(filename, Files.readAllBytes(FileManager.getFile(filename).toPath()));
+        } catch (IOException e) {
+          e.printStackTrace();
+        }
+      });
+    });
+
+    builder.addManifest(defaultMapper.writeValueAsString(manifest));
+
+
+    return builder.buildZip();
+  }
+
+  private void addDoc(ZipFileBuilder builder,
+                      String resourceId,
+                      AbstractResolver<?> resolver,
+                      Consumer<String> function) {
+    addDoc(builder, new ExportItem(resourceId, "", true), resolver, function);
+  }
+
+  private void addDoc(ZipFileBuilder builder,
+                      ExportItem exportItem,
+                      AbstractResolver<?> resolver,
+                      Consumer<String> function) {
+    try {
+      var resourceId = exportItem.getResourceId();
+      var sanitizedResourceId = sanitize(resourceId);
+      builder.addText(sanitizedResourceId, resolver.getSerializedDocument(resourceId));
+      function.accept(sanitizedResourceId);
+    } catch (JsonProcessingException | ElementNotFoundException e) {
+      LOG.warn(
+        "Could not find document with resource id {} with resolver {}",
+        exportItem.getResourceId(),
+        resolver.getClass().getCanonicalName(),
+        e);
+    }
+  }
+
+  private String sanitize(String resourceId) {
+    return resourceId.replaceAll(":", "").replaceAll("\\.", "");
+  }
+
+  private void addAssets(ZipFileBuilder builder,
+                         List<String> assetIds,
+                         StreamPipesApplicationPackage manifest) {
+    assetIds.forEach(assetId -> {
+      try {
+        var asset = getAsset(assetId);
+        asset.remove("_rev");
+        builder.addText(String.valueOf(asset.get("_id")), this.defaultMapper.writeValueAsString(asset));
+        manifest.addAsset(String.valueOf(asset.get("_id")));
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    });
+  }
+
+  private Map<String, Object> getAsset(String assetId) throws IOException {
+    return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().findOne(assetId);
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/generator/ZipFileBuilder.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/generator/ZipFileBuilder.java
new file mode 100644
index 0000000..59edaa8
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/generator/ZipFileBuilder.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.generator;
+
+import org.apache.streampipes.export.constants.ExportConstants;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+public class ZipFileBuilder {
+
+  private final Map<String, byte[]> binaryEntries;
+  private final Map<String, String> textEntries;
+  private final Map<String, File> fileEntries;
+  private String manifest;
+
+  public static ZipFileBuilder create() {
+    return new ZipFileBuilder();
+  }
+
+  private ZipFileBuilder() {
+    this.binaryEntries = new HashMap<>();
+    this.fileEntries = new HashMap<>();
+    this.textEntries = new HashMap<>();
+  }
+
+  public ZipFileBuilder addText(String filename,
+                                String content) {
+    this.textEntries.put(filename, content);
+
+    return this;
+  }
+
+  public ZipFileBuilder addBinary(String filename,
+                                  byte[] content) {
+    this.binaryEntries.put(filename, content);
+
+    return this;
+  }
+
+  public ZipFileBuilder addFile(String filename,
+                                File file) {
+    this.fileEntries.put(filename, file);
+
+    return this;
+  }
+
+  public ZipFileBuilder addManifest(String manifest) {
+    this.manifest = manifest;
+
+    return this;
+  }
+
+  public byte[] buildZip() throws IOException {
+    return makeZip();
+  }
+
+  private byte[] makeZip() throws IOException {
+    byte[] buffer = new byte[1024];
+
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    ZipOutputStream out = new ZipOutputStream(outputStream);
+
+    for (String documentKey : this.textEntries.keySet()) {
+      byte[] document = asBytes(this.textEntries.get(documentKey));
+      addZipEntry(documentKey + ".json", document, out, buffer);
+    }
+
+    for(String binary : this.binaryEntries.keySet()) {
+      addZipEntry(binary, this.binaryEntries.get(binary), out, buffer);
+    }
+
+    addZipEntry(ExportConstants.MANIFEST + ".json", asBytes(manifest), out, buffer);
+    out.closeEntry();
+    out.close();
+    return outputStream.toByteArray();
+  }
+
+  private byte[] asBytes(String document) {
+    return document.getBytes(StandardCharsets.UTF_8);
+  }
+
+  private void addZipEntry(String filename,
+                           byte[] document,
+                           ZipOutputStream out,
+                           byte[] buffer) throws IOException {
+    ZipEntry ze = new ZipEntry(filename);
+    out.putNextEntry(ze);
+
+    try (InputStream in = new ByteArrayInputStream(document)) {
+      int len;
+      while ((len = in.read(buffer)) > 0) {
+        out.write(buffer, 0, len);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/model/PermissionInfo.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/model/PermissionInfo.java
new file mode 100644
index 0000000..5bf2c8b
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/model/PermissionInfo.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.model;
+
+public class PermissionInfo {
+
+  private String instanceId;
+  private Class<?> instanceClass;
+
+  public PermissionInfo(String instanceId, Class<?> className) {
+    this.instanceId = instanceId;
+    this.instanceClass = className;
+  }
+
+  public String getInstanceId() {
+    return instanceId;
+  }
+
+  public void setInstanceId(String instanceId) {
+    this.instanceId = instanceId;
+  }
+
+  public Class<?> getInstanceClass() {
+    return instanceClass;
+  }
+
+  public void setInstanceClass(Class<?> instanceClass) {
+    this.instanceClass = instanceClass;
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/AbstractResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/AbstractResolver.java
new file mode 100644
index 0000000..d4e0ed2
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/AbstractResolver.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.streampipes.commons.exceptions.ElementNotFoundException;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.assets.AssetLink;
+import org.apache.streampipes.model.export.ExportItem;
+import org.apache.streampipes.storage.api.INoSqlStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+import org.lightcouch.DocumentConflictException;
+
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public abstract class AbstractResolver<T> {
+
+  protected ObjectMapper spMapper;
+  protected ObjectMapper defaultMapper;
+
+  public AbstractResolver() {
+    this.spMapper = SerializationUtils.getSpObjectMapper();
+    this.defaultMapper = SerializationUtils.getDefaultObjectMapper();
+  }
+
+  public Set<ExportItem> resolve(Set<AssetLink> assetLinks) {
+    return assetLinks
+      .stream()
+      .map(link -> findDocument(link.getResourceId()))
+      .filter(this::existsDoc)
+      .map(this::convert)
+      .collect(Collectors.toSet());
+  }
+
+  protected boolean existsDoc(T doc) {
+    return Objects.nonNull(doc);
+  }
+
+  public String getSerializedDocument(String resourceId) throws JsonProcessingException, ElementNotFoundException {
+    var document = findDocument(resourceId);
+    if (document != null) {
+      return SerializationUtils.getSpObjectMapper().writeValueAsString(modifyDocumentForExport(document));
+    } else {
+      throw new ElementNotFoundException("Could not find element with resource id " + resourceId);
+    }
+  }
+
+  protected INoSqlStorage getNoSqlStore() {
+    return StorageDispatcher.INSTANCE.getNoSqlStore();
+  }
+
+  public abstract T findDocument(String resourceId);
+
+  public abstract T modifyDocumentForExport(T doc);
+
+  public abstract T readDocument(String serializedDoc) throws JsonProcessingException;
+
+  public abstract ExportItem convert(T document);
+
+  public abstract void writeDocument(String document) throws JsonProcessingException, DocumentConflictException;
+
+  protected abstract T deserializeDocument(String document) throws JsonProcessingException;
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/AdapterResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/AdapterResolver.java
new file mode 100644
index 0000000..d3b7b2c
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/AdapterResolver.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.EventGroundingProcessor;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import org.apache.streampipes.model.connect.adapter.AdapterStreamDescription;
+import org.apache.streampipes.model.export.ExportItem;
+
+public class AdapterResolver extends AbstractResolver<AdapterDescription> {
+
+  @Override
+  public AdapterDescription findDocument(String resourceId) {
+    return getNoSqlStore().getAdapterInstanceStorage().getAdapter(resourceId);
+  }
+
+  @Override
+  public AdapterDescription modifyDocumentForExport(AdapterDescription doc) {
+    doc.setRev(null);
+    doc.setSelectedEndpointUrl(null);
+    if (doc instanceof AdapterStreamDescription) {
+      ((AdapterStreamDescription) doc).setRunning(false);
+    }
+
+    return doc;
+  }
+
+  @Override
+  public AdapterDescription readDocument(String serializedDoc) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, AdapterDescription.class);
+  }
+
+  @Override
+  public ExportItem convert(AdapterDescription document) {
+    return new ExportItem(document.getElementId(), document.getName(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getAdapterInstanceStorage().storeAdapter(deserializeDocument(document));
+  }
+
+  public void writeDocument(String document,
+                            boolean overrideDocument) throws JsonProcessingException {
+    var adapterDescription = deserializeDocument(document);
+    if (overrideDocument) {
+      EventGroundingProcessor.applyOverride(adapterDescription.getEventGrounding().getTransportProtocol());
+    }
+    getNoSqlStore().getAdapterInstanceStorage().storeAdapter(adapterDescription);
+  }
+
+  @Override
+  protected AdapterDescription deserializeDocument(String document) throws JsonProcessingException {
+    return this.spMapper.readValue(document, AdapterDescription.class);
+  }
+
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DashboardResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DashboardResolver.java
new file mode 100644
index 0000000..a756c03
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DashboardResolver.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.dashboard.DashboardItem;
+import org.apache.streampipes.model.dashboard.DashboardModel;
+import org.apache.streampipes.model.export.ExportItem;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class DashboardResolver extends AbstractResolver<DashboardModel> {
+
+  @Override
+  public DashboardModel findDocument(String resourceId) {
+    return getNoSqlStore().getDashboardStorage().getDashboard(resourceId);
+  }
+
+  @Override
+  public DashboardModel modifyDocumentForExport(DashboardModel doc) {
+    doc.setCouchDbRev(null);
+    return doc;
+  }
+
+  @Override
+  protected boolean existsDoc(DashboardModel doc) {
+    return Objects.nonNull(doc) && doc.getCouchDbId() != null;
+  }
+
+  @Override
+  public DashboardModel readDocument(String serializedDoc) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, DashboardModel.class);
+  }
+
+  @Override
+  public ExportItem convert(DashboardModel document) {
+    return new ExportItem(document.getCouchDbId(), document.getName(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getDashboardStorage().storeDashboard(deserializeDocument(document));
+  }
+
+  @Override
+  protected DashboardModel deserializeDocument(String document) throws JsonProcessingException {
+    return this.spMapper.readValue(document, DashboardModel.class);
+  }
+
+  public List<String> getWidgets(String resourceId) {
+    var document = findDocument(resourceId);
+    return document.getWidgets().stream().map(DashboardItem::getId).collect(Collectors.toList());
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DashboardWidgetResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DashboardWidgetResolver.java
new file mode 100644
index 0000000..91d4876
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DashboardWidgetResolver.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.dashboard.DashboardWidgetModel;
+import org.apache.streampipes.model.export.ExportItem;
+
+public class DashboardWidgetResolver extends AbstractResolver<DashboardWidgetModel> {
+
+  @Override
+  public DashboardWidgetModel findDocument(String resourceId) {
+    return getNoSqlStore().getDashboardWidgetStorage().getDashboardWidget(resourceId);
+  }
+
+  @Override
+  public DashboardWidgetModel modifyDocumentForExport(DashboardWidgetModel doc) {
+    doc.setRev(null);
+    return doc;
+  }
+
+  @Override
+  public DashboardWidgetModel readDocument(String serializedDoc) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, DashboardWidgetModel.class);
+  }
+
+  @Override
+  public ExportItem convert(DashboardWidgetModel document) {
+    return new ExportItem(document.getId(), document.getVisualizationName(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getDashboardWidgetStorage().storeDashboardWidget(deserializeDocument(document));
+  }
+
+  @Override
+  protected DashboardWidgetModel deserializeDocument(String document) throws JsonProcessingException {
+    return this.spMapper.readValue(document, DashboardWidgetModel.class);
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataSourceResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataSourceResolver.java
new file mode 100644
index 0000000..14effbb
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataSourceResolver.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.EventGroundingProcessor;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.SpDataStream;
+import org.apache.streampipes.model.export.ExportItem;
+
+public class DataSourceResolver extends AbstractResolver<SpDataStream> {
+
+  @Override
+  public SpDataStream findDocument(String resourceId) {
+    return getNoSqlStore().getDataStreamStorage().getElementById(resourceId);
+  }
+
+  @Override
+  public SpDataStream modifyDocumentForExport(SpDataStream doc) {
+    doc.setRev(null);
+    return doc;
+  }
+
+  @Override
+  public SpDataStream readDocument(String serializedDoc) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, SpDataStream.class);
+  }
+
+  @Override
+  public ExportItem convert(SpDataStream document) {
+    return new ExportItem(document.getElementId(), document.getName(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getDataStreamStorage().createElement(deserializeDocument(document));
+  }
+
+  public void writeDocument(String document,
+                            boolean overrideDocument) throws JsonProcessingException {
+    var dataStream = deserializeDocument(document);
+    if (overrideDocument) {
+      if (dataStream.getEventGrounding() != null) {
+        EventGroundingProcessor.applyOverride(dataStream.getEventGrounding().getTransportProtocol());
+      }
+    }
+    getNoSqlStore().getDataStreamStorage().createElement(dataStream);
+  }
+
+  @Override
+  protected SpDataStream deserializeDocument(String document) throws JsonProcessingException {
+    return this.spMapper.readValue(document, SpDataStream.class);
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataViewResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataViewResolver.java
new file mode 100644
index 0000000..4c81c42
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataViewResolver.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.dashboard.DashboardItem;
+import org.apache.streampipes.model.dashboard.DashboardModel;
+import org.apache.streampipes.model.export.ExportItem;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class DataViewResolver extends AbstractResolver<DashboardModel> {
+
+  @Override
+  public DashboardModel findDocument(String resourceId) {
+    return getNoSqlStore().getDataExplorerDashboardStorage().getDashboard(resourceId);
+  }
+
+  @Override
+  public DashboardModel modifyDocumentForExport(DashboardModel doc) {
+    doc.setCouchDbRev(null);
+    return doc;
+  }
+
+  @Override
+  protected boolean existsDoc(DashboardModel doc) {
+    return Objects.nonNull(doc) && doc.getCouchDbId() != null;
+  }
+
+  @Override
+  public DashboardModel readDocument(String serializedDoc) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, DashboardModel.class);
+  }
+
+  @Override
+  public ExportItem convert(DashboardModel document) {
+    return new ExportItem(document.getCouchDbId(), document.getName(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getDataExplorerDashboardStorage().storeDashboard(deserializeDocument(document));
+  }
+
+  @Override
+  protected DashboardModel deserializeDocument(String document) throws JsonProcessingException {
+    return this.spMapper.readValue(document, DashboardModel.class);
+  }
+
+  public List<String> getWidgets(String resourceId) {
+    var document = findDocument(resourceId);
+    return document.getWidgets().stream().map(DashboardItem::getId).collect(Collectors.toList());
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataViewWidgetResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataViewWidgetResolver.java
new file mode 100644
index 0000000..0414b37
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/DataViewWidgetResolver.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.datalake.DataExplorerWidgetModel;
+import org.apache.streampipes.model.export.ExportItem;
+
+public class DataViewWidgetResolver extends AbstractResolver<DataExplorerWidgetModel> {
+
+  @Override
+  public DataExplorerWidgetModel findDocument(String resourceId) {
+    return getNoSqlStore().getDataExplorerWidgetStorage().getDataExplorerWidget(resourceId);
+  }
+
+  @Override
+  public DataExplorerWidgetModel modifyDocumentForExport(DataExplorerWidgetModel doc) {
+    doc.setRev(null);
+    return doc;
+  }
+
+  @Override
+  public DataExplorerWidgetModel readDocument(String serializedDoc) throws JsonProcessingException {
+   return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, DataExplorerWidgetModel.class);
+  }
+
+  @Override
+  public ExportItem convert(DataExplorerWidgetModel document) {
+    return new ExportItem(document.getId(), document.getWidgetId(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getDataExplorerWidgetStorage().storeDataExplorerWidget(deserializeDocument(document));
+  }
+
+  @Override
+  protected DataExplorerWidgetModel deserializeDocument(String document) throws JsonProcessingException {
+    return this.defaultMapper.readValue(document, DataExplorerWidgetModel.class);
+  }
+
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/FileResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/FileResolver.java
new file mode 100644
index 0000000..e0e2ae8
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/FileResolver.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.export.ExportItem;
+import org.apache.streampipes.model.file.FileMetadata;
+
+public class FileResolver extends AbstractResolver<FileMetadata> {
+
+  @Override
+  public FileMetadata findDocument(String resourceId) {
+    return getNoSqlStore().getFileMetadataStorage().getMetadataById(resourceId);
+  }
+
+  @Override
+  public FileMetadata modifyDocumentForExport(FileMetadata doc) {
+    doc.setRev(null);
+    return doc;
+  }
+
+  @Override
+  public FileMetadata readDocument(String serializedDoc) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, FileMetadata.class);
+  }
+
+  @Override
+  public ExportItem convert(FileMetadata document) {
+    return new ExportItem(document.getFileId(), document.getOriginalFilename(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getFileMetadataStorage().addFileMetadata(deserializeDocument(document));
+  }
+
+  @Override
+  protected FileMetadata deserializeDocument(String document) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(document, FileMetadata.class);
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/MeasurementResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/MeasurementResolver.java
new file mode 100644
index 0000000..c5a86df
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/MeasurementResolver.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.export.ExportItem;
+
+public class MeasurementResolver extends AbstractResolver<DataLakeMeasure> {
+
+  @Override
+  public DataLakeMeasure findDocument(String resourceId) {
+    return getNoSqlStore().getDataLakeStorage().findOne(resourceId);
+  }
+
+  @Override
+  public DataLakeMeasure modifyDocumentForExport(DataLakeMeasure doc) {
+    doc.setRev(null);
+    return doc;
+  }
+
+  @Override
+  public DataLakeMeasure readDocument(String serializedDoc) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, DataLakeMeasure.class);
+  }
+
+  @Override
+  public ExportItem convert(DataLakeMeasure document) {
+    return new ExportItem(document.getElementId(), document.getMeasureName(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getDataLakeStorage().storeDataLakeMeasure(deserializeDocument(document));
+  }
+
+  @Override
+  protected DataLakeMeasure deserializeDocument(String document) throws JsonProcessingException {
+    return this.spMapper.readValue(document, DataLakeMeasure.class);
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/PipelineResolver.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/PipelineResolver.java
new file mode 100644
index 0000000..2117f54
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/resolver/PipelineResolver.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.resolver;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.export.utils.EventGroundingProcessor;
+import org.apache.streampipes.export.utils.SerializationUtils;
+import org.apache.streampipes.model.SpDataSet;
+import org.apache.streampipes.model.export.ExportItem;
+import org.apache.streampipes.model.pipeline.Pipeline;
+
+import java.util.stream.Collectors;
+
+public class PipelineResolver extends AbstractResolver<Pipeline> {
+
+  @Override
+  public Pipeline findDocument(String resourceId) {
+    return getNoSqlStore().getPipelineStorageAPI().getPipeline(resourceId);
+  }
+
+  @Override
+  public Pipeline modifyDocumentForExport(Pipeline doc) {
+    doc.setRev(null);
+    doc.setRestartOnSystemReboot(false);
+    doc.setRunning(false);
+    doc.setSepas(doc.getSepas().stream().peek(s -> s.setSelectedEndpointUrl(null)).collect(Collectors.toList()));
+    doc.setActions(doc.getActions().stream().peek(s -> s.setSelectedEndpointUrl(null)).collect(Collectors.toList()));
+    doc.setStreams(doc.getStreams()
+      .stream()
+      .filter(s -> s instanceof SpDataSet).peek(s -> ((SpDataSet) s).setSelectedEndpointUrl(null))
+      .collect(Collectors.toList()));
+    return doc;
+  }
+
+  @Override
+  public Pipeline readDocument(String serializedDoc) throws JsonProcessingException {
+    return SerializationUtils.getSpObjectMapper().readValue(serializedDoc, Pipeline.class);
+  }
+
+  @Override
+  public ExportItem convert(Pipeline document) {
+    return new ExportItem(document.getPipelineId(), document.getName(), true);
+  }
+
+  @Override
+  public void writeDocument(String document) throws JsonProcessingException {
+    getNoSqlStore().getPipelineStorageAPI().storePipeline(deserializeDocument(document));
+  }
+
+  public void writeDocument(String document,
+                            boolean overrideDocument) throws JsonProcessingException {
+    var pipeline = deserializeDocument(document);
+    if (overrideDocument) {
+      pipeline.setSepas(pipeline.getSepas().stream().peek(processor -> {
+        processor.getInputStreams().forEach(is -> EventGroundingProcessor.applyOverride(is.getEventGrounding().getTransportProtocol()));
+        EventGroundingProcessor.applyOverride(processor.getOutputStream().getEventGrounding().getTransportProtocol());
+      }).collect(Collectors.toList()));
+
+      pipeline.setStreams(pipeline.getStreams().stream().peek(stream -> {
+        EventGroundingProcessor.applyOverride(stream.getEventGrounding().getTransportProtocol());
+      }).collect(Collectors.toList()));
+
+      pipeline.setActions(pipeline.getActions().stream().peek(sink -> {
+        sink.getInputStreams().forEach(is -> EventGroundingProcessor.applyOverride(is.getEventGrounding().getTransportProtocol()));
+      }).collect(Collectors.toList()));
+
+    }
+    getNoSqlStore().getPipelineStorageAPI().storePipeline(pipeline);
+  }
+
+  @Override
+  protected Pipeline deserializeDocument(String document) throws JsonProcessingException {
+    return this.spMapper.readValue(document, Pipeline.class);
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/utils/EventGroundingProcessor.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/utils/EventGroundingProcessor.java
new file mode 100644
index 0000000..15578de
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/utils/EventGroundingProcessor.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.utils;
+
+import org.apache.streampipes.config.backend.BackendConfig;
+import org.apache.streampipes.model.grounding.KafkaTransportProtocol;
+import org.apache.streampipes.model.grounding.MqttTransportProtocol;
+import org.apache.streampipes.model.grounding.TransportProtocol;
+
+public class EventGroundingProcessor {
+
+  public static void applyOverride(TransportProtocol protocol) {
+    if (protocol instanceof KafkaTransportProtocol) {
+      protocol.setBrokerHostname(BackendConfig.INSTANCE.getKafkaHost());
+      ((KafkaTransportProtocol) protocol).setKafkaPort(BackendConfig.INSTANCE.getKafkaPort());
+    } else if (protocol instanceof MqttTransportProtocol) {
+      protocol.setBrokerHostname(BackendConfig.INSTANCE.getMqttHost());
+      ((MqttTransportProtocol) protocol).setPort(BackendConfig.INSTANCE.getMqttPort());
+    }
+  }
+}
diff --git a/streampipes-data-export/src/main/java/org/apache/streampipes/export/utils/SerializationUtils.java b/streampipes-data-export/src/main/java/org/apache/streampipes/export/utils/SerializationUtils.java
new file mode 100644
index 0000000..44eae52
--- /dev/null
+++ b/streampipes-data-export/src/main/java/org/apache/streampipes/export/utils/SerializationUtils.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.export.utils;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.streampipes.serializers.json.JacksonSerializer;
+
+public class SerializationUtils {
+
+  public static ObjectMapper getSpObjectMapper() {
+    return JacksonSerializer.getObjectMapper();
+  }
+
+  public static ObjectMapper getDefaultObjectMapper() {
+    var mapper = new ObjectMapper();
+    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+    return mapper;
+  }
+}
diff --git a/streampipes-dataformat-cbor/pom.xml b/streampipes-dataformat-cbor/pom.xml
index 604a3af..3c2658b 100644
--- a/streampipes-dataformat-cbor/pom.xml
+++ b/streampipes-dataformat-cbor/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-vocabulary</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-dataformat-fst/pom.xml b/streampipes-dataformat-fst/pom.xml
index e6f74b0..519c4bf 100644
--- a/streampipes-dataformat-fst/pom.xml
+++ b/streampipes-dataformat-fst/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-vocabulary</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-dataformat-json/pom.xml b/streampipes-dataformat-json/pom.xml
index 88357bd..3150e08 100644
--- a/streampipes-dataformat-json/pom.xml
+++ b/streampipes-dataformat-json/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-vocabulary</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-dataformat-smile/pom.xml b/streampipes-dataformat-smile/pom.xml
index ac774c8..0fe2690 100644
--- a/streampipes-dataformat-smile/pom.xml
+++ b/streampipes-dataformat-smile/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-vocabulary</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-dataformat/pom.xml b/streampipes-dataformat/pom.xml
index b573e54..80d1057 100644
--- a/streampipes-dataformat/pom.xml
+++ b/streampipes-dataformat/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,7 +32,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/streampipes-extensions/pom.xml b/streampipes-extensions/pom.xml
index cfa8acf..33709e5 100644
--- a/streampipes-extensions/pom.xml
+++ b/streampipes-extensions/pom.xml
@@ -17,49 +17,54 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>streampipes-extensions</artifactId>
     <packaging>pom</packaging>
 
     <modules>
-        <module>streampipes-sinks-databases-jvm</module>
-        <module>streampipes-sinks-internal-jvm</module>
-        <module>streampipes-sinks-brokers-jvm</module>
-        <module>streampipes-processors-filters-jvm</module>
-        <module>streampipes-sinks-databases-flink</module>
+        <module>streampipes-connect-adapters</module>
+        <module>streampipes-connect-adapters-iiot</module>
+
+        <module>streampipes-extensions-all-iiot</module>
+        <module>streampipes-extensions-all-jvm</module>
+
+        <module>streampipes-pipeline-elements-all-jvm</module>
+        <module>streampipes-pipeline-elements-all-flink</module>
+        <module>streampipes-pipeline-elements-data-simulator</module>
+        <module>streampipes-pipeline-elements-shared</module>
+
         <module>streampipes-processors-aggregation-flink</module>
-        <module>streampipes-processors-pattern-detection-flink</module>
+        <module>streampipes-processors-change-detection-jvm</module>
         <module>streampipes-processors-enricher-flink</module>
         <module>streampipes-processors-enricher-jvm</module>
-        <module>streampipes-sources-watertank-simulator</module>
-        <module>streampipes-sources-vehicle-simulator</module>
-        <module>streampipes-processors-transformation-flink</module>
-        <module>streampipes-processors-geo-jvm</module>
-        <module>streampipes-processors-statistics-flink</module>
+        <module>streampipes-processors-filters-jvm</module>
         <module>streampipes-processors-filters-siddhi</module>
+        <module>streampipes-processors-geo-flink</module>
+        <module>streampipes-processors-geo-jvm</module>
+        <module>streampipes-processors-image-processing-jvm</module>
+        <module>streampipes-processors-pattern-detection-flink</module>
+        <module>streampipes-processors-statistics-flink</module>
+        <module>streampipes-processors-transformation-flink</module>
         <module>streampipes-processors-text-mining-flink</module>
         <module>streampipes-processors-text-mining-jvm</module>
-        <module>streampipes-sinks-notifications-jvm</module>
-        <module>streampipes-pipeline-elements-shared</module>
-        <module>streampipes-processors-geo-flink</module>
-        <module>streampipes-processors-image-processing-jvm</module>
         <module>streampipes-processors-transformation-jvm</module>
-        <module>streampipes-pipeline-elements-all-jvm</module>
-        <module>streampipes-pipeline-elements-data-simulator</module>
-        <module>streampipes-connect-adapters</module>
-        <module>streampipes-pipeline-elements-all-flink</module>
-        <module>streampipes-processors-change-detection-jvm</module>
-        <module>streampipes-extensions-all-jvm</module>
-        <module>streampipes-connect-adapters-iiot</module>
+
+        <module>streampipes-sinks-brokers-jvm</module>
+        <module>streampipes-sinks-databases-jvm</module>
+        <module>streampipes-sinks-internal-jvm</module>
+        <module>streampipes-sinks-databases-flink</module>
+        <module>streampipes-sinks-notifications-jvm</module>
+
+        <module>streampipes-sources-watertank-simulator</module>
+        <module>streampipes-sources-vehicle-simulator</module>
     </modules>
 
     <properties>
@@ -84,7 +89,7 @@
         <google-maps-services.version>0.10.0</google-maps-services.version>
         <graalvm.js.version>21.3.0</graalvm.js.version>
         <iotdb.version>0.12.0</iotdb.version>
-        <java-websocket.version>1.4.0</java-websocket.version>
+        <java-websocket.version>1.5.0</java-websocket.version>
         <javax-websocket-client-api.version>1.1</javax-websocket-client-api.version>
         <jsrosbridge.version>0.2.0</jsrosbridge.version>
         <jedis.version>3.3.0</jedis.version>
@@ -98,8 +103,8 @@
         <netty-resolver.version>4.1.72.Final</netty-resolver.version>
         <okhttp.version>3.13.1</okhttp.version>
         <opennlp.version>1.9.0</opennlp.version>
-        <postgresql.version>42.3.3</postgresql.version>
-        <pulsar.version>2.9.1</pulsar.version>
+        <postgresql.version>42.4.1</postgresql.version>
+        <pulsar.version>2.10.1</pulsar.version>
         <quartz.version>2.3.2</quartz.version>
         <scala-lang.version>2.11.12</scala-lang.version>
         <scala-parser-combinators.version>1.1.1</scala-parser-combinators.version>
@@ -125,12 +130,12 @@
         <influxdb.java.version>2.14</influxdb.java.version>
         <eclipse.milo.version>0.6.3</eclipse.milo.version>
         <mysql-binlog-connector.version>0.18.1</mysql-binlog-connector.version>
-        <mysql-connector-java.version>8.0.16</mysql-connector-java.version>
+        <mysql-connector-java.version>8.0.28</mysql-connector-java.version>
         <netty.version>4.1.72.Final</netty.version>
         <nimbus-jose-jwt.version>7.9</nimbus-jose-jwt.version>
         <opencsv.version>5.5.2</opencsv.version>
-        <plc4x.version>0.8.0</plc4x.version>
-        <protobuf.version>3.16.1</protobuf.version>
+        <plc4x.version>0.9.1</plc4x.version>
+        <protobuf.version>3.16.3</protobuf.version>
         <nats.version>2.11.0</nats.version>
 
     </properties>
@@ -616,7 +621,7 @@
             <plugin>
                 <groupId>org.apache.streampipes</groupId>
                 <artifactId>streampipes-maven-plugin</artifactId>
-                <version>0.70.0-SNAPSHOT</version>
+                <version>0.71.0-SNAPSHOT</version>
             </plugin>
         </plugins>
     </build>
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/.idea/workspace.xml b/streampipes-extensions/streampipes-connect-adapters-iiot/.idea/workspace.xml
deleted file mode 100644
index 5cfa370..0000000
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/.idea/workspace.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="AutoImportSettings">
-    <option name="autoReloadType" value="SELECTIVE" />
-  </component>
-  <component name="ChangeListManager">
-    <list default="true" id="d3e2227a-dba3-47e7-b123-6c9059538b23" name="Changes" comment="">
-      <change afterPath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/PullAdapter.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/PullRestAdapter.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioRestAdapter.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioRestAdapter.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/modbus/Plc4xModbusAdapter.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/modbus/Plc4xModbusAdapter.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/Plc4xS7Adapter.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/Plc4xS7Adapter.java" afterDir="false" />
-    </list>
-    <option name="SHOW_DIALOG" value="false" />
-    <option name="HIGHLIGHT_CONFLICTS" value="true" />
-    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
-    <option name="LAST_RESOLUTION" value="IGNORE" />
-  </component>
-  <component name="Git.Settings">
-    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
-  </component>
-  <component name="ProjectId" id="1zENWGAsJxaiZwkmabyYBU9b1cM" />
-  <component name="ProjectViewState">
-    <option name="hideEmptyMiddlePackages" value="true" />
-    <option name="showLibraryContents" value="true" />
-  </component>
-  <component name="PropertiesComponent">
-    <property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
-    <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
-    <property name="last_opened_file_path" value="$PROJECT_DIR$/.." />
-  </component>
-  <component name="RunManager">
-    <configuration name="ConnectAdapterIiotInit" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
-      <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.connect.iiot.ConnectAdapterIiotInit" />
-      <module name="streampipes-connect-adapters-iiot" />
-      <extension name="coverage">
-        <pattern>
-          <option name="PATTERN" value="org.apache.streampipes.connect.iiot.*" />
-          <option name="ENABLED" value="true" />
-        </pattern>
-      </extension>
-      <method v="2">
-        <option name="Make" enabled="true" />
-      </method>
-    </configuration>
-    <recent_temporary>
-      <list>
-        <item itemvalue="Application.ConnectAdapterIiotInit" />
-      </list>
-    </recent_temporary>
-  </component>
-  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
-  <component name="TaskManager">
-    <task active="true" id="Default" summary="Default task">
-      <changelist id="d3e2227a-dba3-47e7-b123-6c9059538b23" name="Changes" comment="" />
-      <created>1633709316229</created>
-      <option name="number" value="Default" />
-      <option name="presentableId" value="Default" />
-      <updated>1633709316229</updated>
-    </task>
-    <servers />
-  </component>
-</project>
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/pom.xml b/streampipes-extensions/streampipes-connect-adapters-iiot/pom.xml
index 5ed13be..71a318a 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/pom.xml
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/pom.xml
@@ -17,16 +17,14 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-extensions</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <artifactId>streampipes-connect-adapters-iiot</artifactId>
 
@@ -39,7 +37,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect-container-worker</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.graalvm.nativeimage</groupId>
@@ -50,17 +48,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-elements-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container-extensions</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -69,10 +67,6 @@
             <artifactId>jackson-module-jaxb-annotations</artifactId>
         </dependency>
         <dependency>
-            <groupId>com.github.shyiko</groupId>
-            <artifactId>mysql-binlog-connector-java</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.influxdb</groupId>
             <artifactId>influxdb-java</artifactId>
         </dependency>
@@ -268,5 +262,4 @@
         </plugins>
         <finalName>streampipes-connect-adapters-iiot</finalName>
     </build>
-
 </project>
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java
index 7298fab..97f0df0 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java
@@ -20,20 +20,16 @@
 
 import org.apache.streampipes.connect.iiot.adapters.influxdb.InfluxDbSetAdapter;
 import org.apache.streampipes.connect.iiot.adapters.influxdb.InfluxDbStreamAdapter;
-import org.apache.streampipes.connect.iiot.adapters.mysql.MySqlSetAdapter;
-import org.apache.streampipes.connect.iiot.adapters.mysql.MySqlStreamAdapter;
-import org.apache.streampipes.connect.iiot.adapters.netio.NetioMQTTAdapter;
-import org.apache.streampipes.connect.iiot.adapters.netio.NetioRestAdapter;
 import org.apache.streampipes.connect.iiot.adapters.opcua.OpcUaAdapter;
 import org.apache.streampipes.connect.iiot.adapters.plc4x.modbus.Plc4xModbusAdapter;
 import org.apache.streampipes.connect.iiot.adapters.plc4x.s7.Plc4xS7Adapter;
 import org.apache.streampipes.connect.iiot.adapters.ros.RosBridgeAdapter;
 import org.apache.streampipes.connect.iiot.adapters.simulator.machine.MachineDataStreamAdapter;
-import org.apache.streampipes.container.extensions.ExtensionsModelSubmitter;
 import org.apache.streampipes.connect.iiot.protocol.set.FileProtocol;
 import org.apache.streampipes.connect.iiot.protocol.set.HttpProtocol;
 import org.apache.streampipes.connect.iiot.protocol.stream.*;
 import org.apache.streampipes.connect.iiot.protocol.stream.pulsar.PulsarProtocol;
+import org.apache.streampipes.container.extensions.ExtensionsModelSubmitter;
 import org.apache.streampipes.container.model.SpServiceDefinition;
 import org.apache.streampipes.container.model.SpServiceDefinitionBuilder;
 
@@ -48,15 +44,11 @@
 						"StreamPipes connect worker containing adapters relevant for the IIoT",
 						"",
 						8001)
-				.registerAdapter(new MySqlStreamAdapter())
-				.registerAdapter(new MySqlSetAdapter())
 				.registerAdapter(new MachineDataStreamAdapter())
 				.registerAdapter(new RosBridgeAdapter())
 				.registerAdapter(new OpcUaAdapter())
 				.registerAdapter(new InfluxDbStreamAdapter())
 				.registerAdapter(new InfluxDbSetAdapter())
-				.registerAdapter(new NetioRestAdapter())
-				.registerAdapter(new NetioMQTTAdapter())
 				.registerAdapter(new Plc4xS7Adapter())
 				.registerAdapter(new Plc4xModbusAdapter())
 				.registerAdapter(new FileProtocol())
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/PullAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/PullAdapter.java
index 2e92cfb..02f1b58 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/PullAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/PullAdapter.java
@@ -51,9 +51,7 @@
     public void startAdapter() throws AdapterException {
         before();
 
-        final Runnable errorThread = () -> {
-            executeAdpaterLogic();
-        };
+        final Runnable errorThread = this::executeAdpaterLogic;
 
         scheduler = Executors.newScheduledThreadPool(1);
         scheduler.schedule(errorThread, 0, TimeUnit.MILLISECONDS);
@@ -61,11 +59,7 @@
     }
 
     private void executeAdpaterLogic() {
-        final Runnable task = () -> {
-
-            pullData();
-
-        };
+        final Runnable task = this::pullData;
 
         scheduler = Executors.newScheduledThreadPool(1);
         ScheduledFuture<?> handle = scheduler.scheduleAtFixedRate(task, 1,
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/Column.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/Column.java
deleted file mode 100644
index 08ee0c5..0000000
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/Column.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.connect.iiot.adapters.mysql;
-
-import org.apache.streampipes.sdk.utils.Datatypes;
-import org.apache.streampipes.vocabulary.SO;
-
-class Column {
-  private String name;
-  private Datatypes type;
-  private Object def;
-  private String domainProperty;
-
-  Column(String name, String dataType, String columnType) {
-    this.name = name;
-    switch (dataType) {
-      case "tinyint":
-      case "smallint":
-      case "mediumint":
-      case "int":
-      case "bit":
-        this.type = Datatypes.Integer;
-        def = 0;
-        break;
-      case "bigint":
-        this.type = Datatypes.Long;
-        def = 0L;
-        break;
-      case "float":
-      case "decimal":   // Watch out for loss of precision
-      case "double":
-        this.type = Datatypes.Float;
-        def = 0.0f;
-        break;
-      case "text":
-      case "varchar":
-      case "char":
-        this.type = Datatypes.String;
-        def = "";
-        break;
-      case "date":
-      case "datetime":
-      case "time":
-      case "timestamp":
-      case "year":
-        this.type = Datatypes.Float;
-        def = System.currentTimeMillis();
-        this.domainProperty = SO.DateTime;
-        break;
-      default:
-        throw new IllegalArgumentException("Type " + type + " not supported.");
-    }
-    if (columnType.equals("tinyint(1)") || columnType.equals("bit(1)")) {
-      this.type = Datatypes.Boolean;
-      def = Boolean.FALSE;
-    }
-    System.out.println("Found column: " + name + ", type: " + this.type + " (sql-type: "
-        + dataType + ", column-tpye: " + columnType + ")");
-  }
-
-  public String getName() {
-    return name;
-  }
-  public Datatypes getType() {
-    return type;
-  }
-  public Object getDefault() {
-    return def;
-  }
-
-  public String getDomainProperty() {
-    return domainProperty;
-  }
-}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlAdapter.java
deleted file mode 100644
index 59fecb9..0000000
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlAdapter.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.connect.iiot.adapters.mysql;
-
-import com.github.shyiko.mysql.binlog.BinaryLogClient;
-import com.github.shyiko.mysql.binlog.event.*;
-import com.github.shyiko.mysql.binlog.event.deserialization.EventDeserializer;
-import org.apache.streampipes.connect.adapter.Adapter;
-import org.apache.streampipes.connect.api.exception.AdapterException;
-import org.apache.streampipes.connect.api.exception.ParseException;
-import org.apache.streampipes.connect.adapter.model.specific.SpecificDataStreamAdapter;
-import org.apache.streampipes.connect.adapter.sdk.ParameterExtractor;
-import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
-import org.apache.streampipes.model.connect.guess.GuessSchema;
-import org.apache.streampipes.model.schema.EventProperty;
-import org.apache.streampipes.model.schema.EventSchema;
-import org.apache.streampipes.sdk.builder.adapter.SpecificDataStreamAdapterBuilder;
-import org.apache.streampipes.sdk.builder.PrimitivePropertyBuilder;
-import org.apache.streampipes.sdk.helpers.Labels;
-import org.apache.streampipes.vocabulary.SO;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.sql.*;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-public class MySqlAdapter extends SpecificDataStreamAdapter {
-
-  public static final String ID = "http://streampipes.org/adapter/specific/mysql";
-
-  private static String MYSQL_HOST = "MYSQL_HOST";
-  private static String MYSQL_USER = "MYSQL_USER";
-  private static String MYSQL_PASS = "MYSQL_PASS";
-  private static String MYSQL_DB = "MYSQL_DB";
-  private static String MYSQL_TABLE = "MYSQL_TABLE";
-  private static String MYSQL_PORT = "MYSQL_PORT";
-
-  private String host;
-  private String user;
-  private String pass;
-  private String database;
-  private String table;
-  private String port;
-
-  private boolean dataComing = false;
-  private List<Column> tableSchema;
-  private BinaryLogClient client;
-
-  public MySqlAdapter() {
-  }
-
-  public MySqlAdapter(SpecificAdapterStreamDescription adapterDescription) {
-    super(adapterDescription);
-
-    getConfigurations(adapterDescription);
-  }
-
-  @Override
-  public SpecificAdapterStreamDescription declareModel() {
-    //TODO: Add Icon
-    SpecificAdapterStreamDescription description = SpecificDataStreamAdapterBuilder.create(ID,
-            "MySql Adapter",
-            "Creates a data stream for a SQL table")
-            .iconUrl("sql.png")
-            .requiredTextParameter(Labels.from(MYSQL_HOST, "Hostname", "Hostname of the MySql Server"))
-            .requiredTextParameter(Labels.from(MYSQL_USER, "Username", "Username of the user"))
-            .requiredTextParameter(Labels.from(MYSQL_PASS, "Password", "Password of the user"))
-            .requiredTextParameter(Labels.from(MYSQL_DB, "Database", "Database in which the table is located"))
-            .requiredTextParameter(Labels.from(MYSQL_TABLE, "Table", "Table which should be watched"))
-            .requiredIntegerParameter(Labels.from(MYSQL_PORT, "Port", "Port of the MySql Server. Default: 3306"), 3306)
-            .build();
-
-    description.setAppId(ID);
-    return  description;
-  }
-
-  @Override
-  public void startAdapter() throws AdapterException {
-    checkJdbcDriver();
-    extractTableInformation();
-
-    // Connect BinaryLogClient
-    client = new BinaryLogClient(host, Integer.parseInt(port), user, pass);
-    EventDeserializer eventDeserializer = new EventDeserializer();
-    eventDeserializer.setCompatibilityMode(
-            EventDeserializer.CompatibilityMode.DATE_AND_TIME_AS_LONG,
-            EventDeserializer.CompatibilityMode.CHAR_AND_BINARY_AS_BYTE_ARRAY
-    );
-    client.setEventDeserializer(eventDeserializer);
-    client.registerEventListener(event -> sendEvent(event));
-    try {
-      client.connect();
-    } catch (IOException e) {
-      throw new AdapterException(e.getMessage());
-    }
-  }
-
-  private void sendEvent(Event event) {
-    // An event can contain multiple insertions/updates
-    if (event.getHeader().getEventType() == EventType.TABLE_MAP) {
-      // Check table and database, if the next event should be streamed
-      if (((TableMapEventData) event.getData()).getDatabase().equals(database)
-              && ((TableMapEventData) event.getData()).getTable().equals((table))) {
-        dataComing = true;
-      }
-    }
-    if (dataComing) {
-      if (EventType.isUpdate(event.getHeader().getEventType())) {
-        for (Entry<Serializable[], Serializable[]> en : ((UpdateRowsEventData) event.getData()).getRows()) {
-          sendChange(en.getValue());
-        }
-        dataComing = false;
-      } else if (EventType.isWrite(event.getHeader().getEventType())) {
-        for (Serializable[] s : ((WriteRowsEventData) event.getData()).getRows()) {
-          sendChange(s);
-        }
-        dataComing = false;
-      }
-    }
-  }
-
-  private void sendChange(Serializable[] rows) {
-    Map<String, Object> out = new HashMap<>();
-    for (int i = 0; i < rows.length; i++) {
-      if (rows[i] != null) {
-        if (rows[i] instanceof byte[]) {
-          // Strings are sent in byte arrays and have to be converted. TODO: Check that encoding is correct
-          out.put(tableSchema.get(i).getName(), new String((byte[])rows[i]));
-        } else {
-          out.put(tableSchema.get(i).getName(), rows[i]);
-        }
-      } else {
-        out.put(tableSchema.get(i).getName(), tableSchema.get(i).getDefault());
-      }
-    }
-    adapterPipeline.process(out);
-  }
-
-  @Override
-  public void stopAdapter() throws AdapterException {
-    try {
-      client.disconnect();
-    } catch (IOException e) {
-      throw new AdapterException("Thrown exception: " + e.getMessage());
-    }
-  }
-
-  @Override
-  public Adapter getInstance(SpecificAdapterStreamDescription adapterDescription) {
-    return new MySqlAdapter(adapterDescription);
-  }
-
-  @Override
-  public GuessSchema getSchema(SpecificAdapterStreamDescription adapterDescription)
-          throws AdapterException, ParseException {
-    // Load JDBC Driver, connect JDBC Driver, Extract information, disconnect JDBC Driver
-    EventSchema eventSchema = new EventSchema();
-    GuessSchema guessSchema = new GuessSchema();
-    List<EventProperty> allProperties = new ArrayList<>();
-
-    getConfigurations(adapterDescription);
-
-    checkJdbcDriver();
-    extractTableInformation();
-
-    for (Column column : tableSchema) {
-      if (SO.DateTime.equals(column.getDomainProperty())) {
-        allProperties.add(PrimitivePropertyBuilder
-                .create(column.getType(), column.getName())
-                .label(column.getName())
-                .domainProperty(SO.DateTime)
-                .build());
-      } else {
-        allProperties.add(PrimitivePropertyBuilder
-                .create(column.getType(), column.getName())
-                .label(column.getName())
-                .build());
-      }
-
-    }
-
-    eventSchema.setEventProperties(allProperties);
-    guessSchema.setEventSchema(eventSchema);
-
-    return guessSchema;
-  }
-
-  @Override
-  public String getId() {
-    return ID;
-  }
-
-  private void getConfigurations(SpecificAdapterStreamDescription adapterDescription) {
-    ParameterExtractor extractor = new ParameterExtractor(adapterDescription.getConfig());
-
-    this.host = extractor.singleValue(MYSQL_HOST, String.class);
-    this.user = extractor.singleValue(MYSQL_USER, String.class);
-    this.pass = extractor.singleValue(MYSQL_PASS, String.class);
-    this.database = extractor.singleValue(MYSQL_DB, String.class);
-    this.table = extractor.singleValue(MYSQL_TABLE, String.class);
-    this.port = extractor.singleValue(MYSQL_PORT, String.class);
-  }
-
-  private void checkJdbcDriver() throws AdapterException {
-    try {
-      Class.forName("com.mysql.cj.jdbc.Driver");
-    } catch (ClassNotFoundException e) {
-      throw new AdapterException("MySql Driver not found.");
-    }
-  }
-
-  private void extractTableInformation() throws AdapterException {
-    String server = "jdbc:mysql://" + host + ":" + port + "/" + "?sslMode=DISABLED&allowPublicKeyRetrieval=true";
-    ResultSet resultSet = null;
-    tableSchema = new ArrayList<>();
-
-    String query = "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE FROM "
-            + "INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ? ORDER BY "
-            + "ORDINAL_POSITION ASC;";
-
-    try (Connection con = DriverManager.getConnection(server, user, pass);
-         PreparedStatement statement = con.prepareStatement(query)) {
-
-      statement.setString(1, table);
-      statement.setString(2, database);
-      resultSet = statement.executeQuery();
-
-      if (resultSet.next()) {
-        do {
-          String name = resultSet.getString("COLUMN_NAME");
-          String dataType = resultSet.getString("DATA_TYPE");
-          String columnType = resultSet.getString("COLUMN_TYPE");
-          tableSchema.add(new Column(name, dataType, columnType));
-        } while(resultSet.next());
-      } else {
-        // No columns found -> Table/Database does not exist
-        throw new IllegalArgumentException("Database/table not found");
-      }
-    } catch (SQLException e) {
-      throw new AdapterException("SqlException: " + e.getMessage()
-              + ", Error code: " + e.getErrorCode()
-              + ", SqlState: " + e.getSQLState());
-    } finally {
-      try {
-        resultSet.close();
-      } catch (Exception e) {}
-    }
-  }
-}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlClient.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlClient.java
deleted file mode 100644
index 251f16a..0000000
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlClient.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.connect.iiot.adapters.mysql;
-
-import org.apache.streampipes.connect.api.exception.AdapterException;
-import org.apache.streampipes.model.connect.guess.GuessSchema;
-import org.apache.streampipes.model.schema.EventProperty;
-import org.apache.streampipes.model.schema.EventSchema;
-import org.apache.streampipes.sdk.builder.PrimitivePropertyBuilder;
-import org.apache.streampipes.vocabulary.SO;
-
-import java.sql.*;
-import java.util.ArrayList;
-import java.util.List;
-
-public class MySqlClient {
-
-  public static final String ID = "http://streampipes.org/adapter/specific/mysql";
-
-  static final String HOST = "mysqlHost";
-  static final String PORT = "mysqlPort";
-  static final String DATABASE = "mysqlDatabase";
-  static final String TABLE = "mysqlTable";
-  static final String USER = "mysqlUser";
-  static final String PASSWORD = "mysqlPassword";
-
-  static final String REPLACE_NULL_VALUES = "replaceNullValues";
-  static final String DO_REPLACE_NULL_VALUES = "doReplaceNullValues";
-  static final String DO_NOT_REPLACE_NULL_VALUES = "doNotReplaceNullValues";
-
-  private String host;
-  private Integer port;
-  private String database;
-  private String table;
-
-  private String username;
-  private String password;
-
-
-  private List<Column> columns;
-
-  Connection connection;
-
-  MySqlClient(String host,
-              int port,
-              String database,
-              String table,
-              String username,
-              String password) {
-    this.host = host;
-    this.port = port;
-    this.database = database;
-    this.table = table;
-    this.username = username;
-    this.password = password;
-
-    connection = null;
-  }
-
-  public void connect() throws AdapterException {
-    checkJdbcDriver();
-    String server = "jdbc:mysql://" + host + ":" + port + "/" + "?sslMode=DISABLED&allowPublicKeyRetrieval=true";
-    try {
-      connection = DriverManager.getConnection(server, username, password);
-    } catch (SQLException e) {
-      throw new AdapterException("Could not connect to server: " + e.getMessage());
-    }
-  }
-
-  public void disconnect() throws AdapterException {
-    if (connection != null) {
-      try {
-        connection.close();
-      } catch (SQLException e) {
-        throw new AdapterException("Error while disconnecting: " + e.getMessage());
-      }
-      connection = null;
-    }
-  }
-
-  public GuessSchema getSchema() throws AdapterException {
-    connect();
-    loadColumns();
-
-    EventSchema eventSchema = new EventSchema();
-    GuessSchema guessSchema = new GuessSchema();
-    List<EventProperty> allProperties = new ArrayList<>();
-
-    for (Column column : columns) {
-      if (SO.DateTime.equals(column.getDomainProperty())) {
-        allProperties.add(PrimitivePropertyBuilder
-                .create(column.getType(), column.getName())
-                .label(column.getName())
-                .domainProperty(SO.DateTime)
-                .build());
-      } else {
-        allProperties.add(PrimitivePropertyBuilder
-                .create(column.getType(), column.getName())
-                .label(column.getName())
-                .build());
-      }
-    }
-
-    eventSchema.setEventProperties(allProperties);
-    guessSchema.setEventSchema(eventSchema);
-
-    disconnect();
-    return guessSchema;
-  }
-
-  /**
-   * Checks that the MySql-JDBC-Driver is "installed". Throws an AdapterException otherwise
-   */
-  private void checkJdbcDriver() throws AdapterException {
-    try {
-      Class.forName("com.mysql.cj.jdbc.Driver");
-    } catch (ClassNotFoundException e) {
-      throw new AdapterException("MySql Driver not found.");
-    }
-  }
-
-  /**
-   * Fills the columns with the columns from the SQL Table
-   */
-  public void loadColumns() throws AdapterException {
-    if (connection == null) {
-      throw new AdapterException("Client must be connected in order to load the columns");
-    }
-    ResultSet resultSet = null;
-    columns = new ArrayList<>();
-
-    String query = "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE FROM "
-            + "INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ? ORDER BY "
-            + "ORDINAL_POSITION ASC;";
-
-    try (PreparedStatement statement = connection.prepareStatement(query)) {
-
-      statement.setString(1, table);
-      statement.setString(2, database);
-      resultSet = statement.executeQuery();
-
-      if (resultSet.next()) {
-        do {
-          String name = resultSet.getString("COLUMN_NAME");
-          String dataType = resultSet.getString("DATA_TYPE");
-          String columnType = resultSet.getString("COLUMN_TYPE");
-          columns.add(new Column(name, dataType, columnType));
-        } while(resultSet.next());
-      } else {
-        // No columns found -> Table/Database does not exist
-        throw new IllegalArgumentException("Database/table not found");
-      }
-    } catch (SQLException e) {
-      throw new AdapterException("SqlException while loading columns: " + e.getMessage()
-              + ", Error code: " + e.getErrorCode()
-              + ", SqlState: " + e.getSQLState());
-    } finally {
-      try {
-        resultSet.close();
-      } catch (Exception e) {}
-    }
-  }
-
-  public String getHost() {
-    return host;
-  }
-
-  public Integer getPort() {
-    return port;
-  }
-
-  public String getDatabase() {
-    return database;
-  }
-
-  public String getTable() {
-    return table;
-  }
-
-  public String getUsername() {
-    return username;
-  }
-
-  public String getPassword() {
-    return password;
-  }
-
-  public List<Column> getColumns() {
-    return columns;
-  }
-
-  public boolean isConnected() {
-    return connection != null;
-  }
-
-  Connection getConnection() {
-    return connection;
-  }
-}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlSetAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlSetAdapter.java
deleted file mode 100644
index 87769ee..0000000
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlSetAdapter.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.connect.iiot.adapters.mysql;
-
-import org.apache.streampipes.connect.adapter.Adapter;
-import org.apache.streampipes.connect.api.exception.AdapterException;
-import org.apache.streampipes.connect.api.exception.ParseException;
-import org.apache.streampipes.connect.adapter.model.specific.SpecificDataSetAdapter;
-import org.apache.streampipes.connect.adapter.sdk.ParameterExtractor;
-import org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription;
-import org.apache.streampipes.model.connect.guess.GuessSchema;
-import org.apache.streampipes.sdk.builder.adapter.SpecificDataSetAdapterBuilder;
-import org.apache.streampipes.sdk.helpers.Labels;
-import org.apache.streampipes.sdk.helpers.Locales;
-import org.apache.streampipes.sdk.helpers.Options;
-import org.apache.streampipes.sdk.helpers.Tuple2;
-import org.apache.streampipes.sdk.utils.Assets;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashMap;
-import java.util.Map;
-
-public class MySqlSetAdapter extends SpecificDataSetAdapter {
-
-    public static final String ID = "org.apache.streampipes.connect.iiot.adapters.mysql.set";
-
-    private MySqlClient mySqlClient;
-    private Thread fetchDataThread;
-
-    private boolean replaceNullValues;
-
-    public static class FetchDataThread implements Runnable {
-
-        MySqlSetAdapter mySqlSetAdapter;
-        MySqlClient mySqlClient;
-
-        public FetchDataThread(MySqlSetAdapter mySqlSetAdapter) throws AdapterException {
-            this.mySqlSetAdapter = mySqlSetAdapter;
-            this.mySqlClient = mySqlSetAdapter.getMySqlClient();
-
-            mySqlClient.connect();
-            mySqlClient.loadColumns();
-        }
-
-        @Override
-        public void run() {
-            if (!mySqlClient.isConnected()) {
-                System.out.println("Cannot start PollingThread, when the client is not connected");
-                return;
-            }
-            // No batch approach like in the influx adapter due to the lack of a unique key in the table
-            // Create the columnString:
-            StringBuilder sb = new StringBuilder();
-            for (Column column : mySqlClient.getColumns()) {
-                sb.append(column.getName()).append(", ");
-            }
-            sb.setLength(Math.max(0, sb.length() - 2));
-
-            String query = "SELECT " + sb.toString() + " FROM " + mySqlClient.getDatabase() + "." + mySqlClient.getTable();
-
-            try (Statement statement = mySqlClient.getConnection().createStatement()) {
-                boolean executed = statement.execute(query);
-                if (executed) {
-                    ResultSet resultSet = statement.getResultSet();
-                    while (resultSet.next()) {
-
-                        // Retrieve by column name
-                        Map<String, Object> event = new HashMap<>();
-                        for (Column column : mySqlClient.getColumns()) {
-                            Object in = resultSet.getObject(column.getName());
-                            if (in == null) {
-                                if (mySqlSetAdapter.replaceNullValues) {
-                                    in = column.getDefault();
-                                } else {
-                                    // We do not want to send this event (replaceNullValues == false)
-                                    event = null;
-                                    break;
-                                }
-                            }
-                            event.put(column.getName(), in);
-                        }
-                        if (event != null) {
-                            mySqlSetAdapter.send(event);
-                        }
-                    }
-                    resultSet.close();
-                }
-            } catch (SQLException e) {
-                System.out.println(e.getMessage());
-            }
-
-            try {
-                mySqlClient.disconnect();
-            } catch (AdapterException e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    public MySqlSetAdapter() {
-    }
-
-    public MySqlSetAdapter(SpecificAdapterSetDescription adapterDescription) {
-        super(adapterDescription);
-
-        getConfigurations(adapterDescription);
-    }
-
-
-    @Override
-    public SpecificAdapterSetDescription declareModel() {
-        SpecificAdapterSetDescription description = SpecificDataSetAdapterBuilder.create(ID)
-                .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-                .withLocales(Locales.EN)
-                .requiredTextParameter(Labels.withId(MySqlClient.HOST))
-                .requiredIntegerParameter(Labels.withId(MySqlClient.PORT), 3306)
-                .requiredTextParameter(Labels.withId(MySqlClient.DATABASE))
-                .requiredTextParameter(Labels.withId(MySqlClient.TABLE))
-                .requiredTextParameter(Labels.withId(MySqlClient.USER))
-                .requiredSecret(Labels.withId(MySqlClient.PASSWORD))
-                .requiredSingleValueSelection(Labels.withId(MySqlClient.REPLACE_NULL_VALUES),
-                        Options.from(
-                                new Tuple2<>("Yes", MySqlClient.DO_REPLACE_NULL_VALUES),
-                                new Tuple2<>("No", MySqlClient.DO_NOT_REPLACE_NULL_VALUES)))
-                .build();
-
-        description.setAppId(ID);
-        return description;
-    }
-
-    @Override
-    public void startAdapter() throws AdapterException {
-        fetchDataThread = new Thread(new FetchDataThread(this));
-        fetchDataThread.start();
-    }
-
-    @Override
-    public void stopAdapter() throws AdapterException {
-        fetchDataThread.interrupt();
-        try {
-            fetchDataThread.join();
-        } catch (InterruptedException e) {
-            throw new AdapterException("Unexpected Error while joining polling thread: " + e.getMessage());
-        }
-    }
-
-    @Override
-    public Adapter getInstance(SpecificAdapterSetDescription adapterDescription) {
-        return new MySqlSetAdapter(adapterDescription);
-    }
-
-    @Override
-    public GuessSchema getSchema(SpecificAdapterSetDescription adapterDescription) throws AdapterException, ParseException {
-        getConfigurations(adapterDescription);
-        return mySqlClient.getSchema();
-    }
-
-    @Override
-    public String getId() {
-        return ID;
-    }
-
-    private void send(Map<String, Object> map) {
-        adapterPipeline.process(map);
-    }
-
-    private void getConfigurations(SpecificAdapterSetDescription adapterDescription) {
-        ParameterExtractor extractor = new ParameterExtractor(adapterDescription.getConfig());
-
-        String replace = extractor.selectedSingleValueInternalName(MySqlClient.REPLACE_NULL_VALUES);
-        replaceNullValues = replace.equals(MySqlClient.DO_REPLACE_NULL_VALUES);
-
-        mySqlClient = new MySqlClient(
-                extractor.singleValue(MySqlClient.HOST, String.class),
-                extractor.singleValue(MySqlClient.PORT, Integer.class),
-                extractor.singleValue(MySqlClient.DATABASE, String.class),
-                extractor.singleValue(MySqlClient.TABLE, String.class),
-                extractor.singleValue(MySqlClient.USER, String.class),
-                extractor.secretValue(MySqlClient.PASSWORD));
-    }
-
-    public MySqlClient getMySqlClient() {
-        return mySqlClient;
-    }
-}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlStreamAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlStreamAdapter.java
deleted file mode 100644
index c36e14a..0000000
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/mysql/MySqlStreamAdapter.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.connect.iiot.adapters.mysql;
-
-import com.github.shyiko.mysql.binlog.BinaryLogClient;
-import com.github.shyiko.mysql.binlog.event.*;
-import com.github.shyiko.mysql.binlog.event.deserialization.EventDeserializer;
-import org.apache.streampipes.connect.adapter.Adapter;
-import org.apache.streampipes.connect.api.exception.AdapterException;
-import org.apache.streampipes.connect.api.exception.ParseException;
-import org.apache.streampipes.connect.adapter.model.specific.SpecificDataStreamAdapter;
-import org.apache.streampipes.connect.adapter.sdk.ParameterExtractor;
-import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
-import org.apache.streampipes.model.connect.guess.GuessSchema;
-import org.apache.streampipes.sdk.builder.adapter.SpecificDataStreamAdapterBuilder;
-import org.apache.streampipes.sdk.helpers.Labels;
-import org.apache.streampipes.sdk.helpers.Locales;
-import org.apache.streampipes.sdk.helpers.Options;
-import org.apache.streampipes.sdk.helpers.Tuple2;
-import org.apache.streampipes.sdk.utils.Assets;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
-public class MySqlStreamAdapter extends SpecificDataStreamAdapter {
-
-    public static final String ID = "org.apache.streampipes.connect.iiot.adapters.mysql.stream";
-
-    private MySqlClient mySqlClient;
-    private BinaryLogClient binaryLogClient;
-
-    private Thread subscriptionThread  = new Thread(()-> {
-        try {
-            binaryLogClient.connect();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    });
-
-    private boolean replaceNullValues;
-    private boolean dataComing = false;
-
-    public MySqlStreamAdapter() {
-    }
-
-    public MySqlStreamAdapter(SpecificAdapterStreamDescription adapterDescription) {
-        super(adapterDescription);
-
-        getConfigurations(adapterDescription);
-    }
-
-    @Override
-    public SpecificAdapterStreamDescription declareModel() {
-        SpecificAdapterStreamDescription description = SpecificDataStreamAdapterBuilder.create(ID)
-                .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-                .withLocales(Locales.EN)
-                .requiredTextParameter(Labels.withId(MySqlClient.HOST))
-                .requiredIntegerParameter(Labels.withId(MySqlClient.PORT), 3306)
-                .requiredTextParameter(Labels.withId(MySqlClient.DATABASE))
-                .requiredTextParameter(Labels.withId(MySqlClient.TABLE))
-                .requiredTextParameter(Labels.withId(MySqlClient.USER))
-                .requiredSecret(Labels.withId(MySqlClient.PASSWORD))
-                .requiredSingleValueSelection(Labels.withId(MySqlClient.REPLACE_NULL_VALUES),
-                        Options.from(
-                                new Tuple2<>("Yes", MySqlClient.DO_REPLACE_NULL_VALUES),
-                                new Tuple2<>("No", MySqlClient.DO_NOT_REPLACE_NULL_VALUES)))
-                .build();
-
-        description.setAppId(ID);
-        return description;
-    }
-
-    @Override
-    public void startAdapter() throws AdapterException {
-        // Making sure, that the columns are all loaded
-        mySqlClient.connect();
-        mySqlClient.loadColumns();
-        mySqlClient.disconnect();
-
-        // Connect BinaryLogClient
-        binaryLogClient = new BinaryLogClient(
-                mySqlClient.getHost(),
-                mySqlClient.getPort(),
-                mySqlClient.getUsername(),
-                mySqlClient.getPassword());
-
-        EventDeserializer eventDeserializer = new EventDeserializer();
-        eventDeserializer.setCompatibilityMode(
-                EventDeserializer.CompatibilityMode.DATE_AND_TIME_AS_LONG,
-                EventDeserializer.CompatibilityMode.CHAR_AND_BINARY_AS_BYTE_ARRAY
-        );
-        binaryLogClient.setEventDeserializer(eventDeserializer);
-        binaryLogClient.registerEventListener(event -> sendEvent(event));
-        subscriptionThread.start();
-    }
-
-
-    private void sendEvent(Event event) {
-        // An event can contain multiple insertions/updates
-        if (event.getHeader().getEventType() == EventType.TABLE_MAP) {
-            // Check table and database, if the next event should be streamed
-            if (((TableMapEventData) event.getData()).getDatabase().equals(mySqlClient.getDatabase())
-                    && ((TableMapEventData) event.getData()).getTable().equals((mySqlClient.getTable()))) {
-                dataComing = true;
-            }
-        }
-        if (dataComing) {
-            if (EventType.isUpdate(event.getHeader().getEventType())) {
-                for (Map.Entry<Serializable[], Serializable[]> en : ((UpdateRowsEventData) event.getData()).getRows()) {
-                    sendChange(en.getValue());
-                }
-                dataComing = false;
-            } else if (EventType.isWrite(event.getHeader().getEventType())) {
-                for (Serializable[] s : ((WriteRowsEventData) event.getData()).getRows()) {
-                    sendChange(s);
-                }
-                dataComing = false;
-            }
-        }
-    }
-
-    private void sendChange(Serializable[] rows) {
-        Map<String, Object> out = new HashMap<>();
-        for (int i = 0; i < rows.length; i++) {
-            if (rows[i] != null) {
-                if (rows[i] instanceof byte[]) {
-                    // Strings are sent in byte arrays and have to be converted.
-                    //TODO: Check that encoding is correct
-                    out.put(mySqlClient.getColumns().get(i).getName(), new String((byte[])rows[i]));
-                } else {
-                    out.put(mySqlClient.getColumns().get(i).getName(), rows[i]);
-                }
-            } else if (replaceNullValues) {
-                out.put(mySqlClient.getColumns().get(i).getName(), mySqlClient.getColumns().get(i).getDefault());
-            } else {
-                // We should skip events with null values
-                return;
-            }
-        }
-        adapterPipeline.process(out);
-    }
-
-    @Override
-    public void stopAdapter() throws AdapterException {
-        try {
-            binaryLogClient.disconnect();
-            subscriptionThread.join();
-        } catch (IOException | InterruptedException e) {
-            throw new AdapterException("Thrown exception: " + e.getMessage());
-        }
-    }
-
-    @Override
-    public Adapter getInstance(SpecificAdapterStreamDescription adapterDescription) {
-        return new MySqlStreamAdapter(adapterDescription);
-    }
-
-    @Override
-    public GuessSchema getSchema(SpecificAdapterStreamDescription adapterDescription) throws AdapterException, ParseException {
-        getConfigurations(adapterDescription);
-        return mySqlClient.getSchema();
-    }
-
-    @Override
-    public String getId() {
-        return ID;
-    }
-
-    private void getConfigurations(SpecificAdapterStreamDescription adapterDescription) {
-        ParameterExtractor extractor = new ParameterExtractor(adapterDescription.getConfig());
-
-        String replace = extractor.selectedSingleValueInternalName(MySqlClient.REPLACE_NULL_VALUES);
-        replaceNullValues = replace.equals(MySqlClient.DO_REPLACE_NULL_VALUES);
-
-        mySqlClient = new MySqlClient(
-                extractor.singleValue(MySqlClient.HOST, String.class),
-                extractor.singleValue(MySqlClient.PORT, Integer.class),
-                extractor.singleValue(MySqlClient.DATABASE, String.class),
-                extractor.singleValue(MySqlClient.TABLE, String.class),
-                extractor.singleValue(MySqlClient.USER, String.class),
-                extractor.secretValue(MySqlClient.PASSWORD));
-    }
-}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/MiloOpcUaConfigurationProvider.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/MiloOpcUaConfigurationProvider.java
index e4336d8..7145858 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/MiloOpcUaConfigurationProvider.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/MiloOpcUaConfigurationProvider.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.connect.iiot.adapters.opcua;
 
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.connect.iiot.adapters.opcua.configuration.SpOpcUaConfig;
 import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
 import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfigBuilder;
@@ -31,10 +32,11 @@
 import java.net.URISyntaxException;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
 
 public class MiloOpcUaConfigurationProvider {
 
-  public OpcUaClientConfig makeClientConfig(SpOpcUaConfig spOpcConfig) throws Exception {
+  public OpcUaClientConfig makeClientConfig(SpOpcUaConfig spOpcConfig) throws ExecutionException, InterruptedException, SpConfigurationException, URISyntaxException {
     String opcServerUrl = spOpcConfig.getOpcServerURL();
     List<EndpointDescription> endpoints = DiscoveryClient.getEndpoints(opcServerUrl).get();
     String host = opcServerUrl.split("://")[1].split(":")[0];
@@ -43,7 +45,7 @@
             .stream()
             .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
             .findFirst()
-            .orElseThrow(() -> new Exception("No endpoint with security policy none"));
+            .orElseThrow(() -> new SpConfigurationException("No endpoint with security policy none"));
 
     tmpEndpoint = updateEndpointUrl(tmpEndpoint, host);
     endpoints = Collections.singletonList(tmpEndpoint);
@@ -51,7 +53,7 @@
     EndpointDescription endpoint = endpoints
             .stream()
             .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
-            .findFirst().orElseThrow(() -> new Exception("no desired endpoints returned"));
+            .findFirst().orElseThrow(() -> new SpConfigurationException("no desired endpoints returned"));
 
     return buildConfig(endpoint, spOpcConfig);
   }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
index 525ca38..34016cb 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.connect.iiot.adapters.opcua;
 
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.connect.adapter.Adapter;
 import org.apache.streampipes.connect.adapter.util.PollingSettings;
 import org.apache.streampipes.connect.api.exception.AdapterException;
@@ -30,6 +31,7 @@
 import org.apache.streampipes.model.AdapterType;
 import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription;
 import org.apache.streampipes.model.staticproperty.StaticProperty;
 import org.apache.streampipes.sdk.StaticProperties;
 import org.apache.streampipes.sdk.builder.adapter.SpecificDataStreamAdapterBuilder;
@@ -41,49 +43,69 @@
 import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem;
 import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
 import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
 import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
 
 public class OpcUaAdapter extends PullAdapter implements SupportsRuntimeConfig {
 
     public static final String ID = "org.apache.streampipes.connect.iiot.adapters.opcua";
+    private static final Logger LOG = LoggerFactory.getLogger(OpcUaAdapter.class);
 
     private int pullingIntervalMilliSeconds;
     private SpOpcUaClient spOpcUaClient;
     private List<OpcNode> allNodes;
     private List<NodeId> allNodeIds;
     private int numberProperties;
-    private Map<String, Object> event;
+    private final Map<String, Object> event;
+
+    /**
+     * This variable is used to map the node ids during the subscription to the labels of the nodes
+     */
+    private final Map<String, String> nodeIdToLabelMapping;
 
     public OpcUaAdapter() {
         super();
         this.numberProperties = 0;
         this.event = new HashMap<>();
+        this.nodeIdToLabelMapping = new HashMap<>();
     }
 
     public OpcUaAdapter(SpecificAdapterStreamDescription adapterStreamDescription) {
         super(adapterStreamDescription);
         this.numberProperties = 0;
         this.event = new HashMap<>();
+        this.nodeIdToLabelMapping = new HashMap<>();
     }
 
     @Override
     protected void before() throws AdapterException {
 
         this.allNodeIds = new ArrayList<>();
+        List<String> deleteKeys = this.adapterDescription
+          .getSchemaRules()
+          .stream()
+          .filter(rule -> rule instanceof DeleteRuleDescription)
+          .map(rule -> ((DeleteRuleDescription) rule).getRuntimeKey())
+          .collect(Collectors.toList());
+
         try {
             this.spOpcUaClient.connect();
-            OpcUaNodeBrowser browserClient = new OpcUaNodeBrowser(this.spOpcUaClient.getClient(), this.spOpcUaClient.getSpOpcConfig());
-            this.allNodes = browserClient.findNodes();
+            OpcUaNodeBrowser browserClient =
+                    new OpcUaNodeBrowser(this.spOpcUaClient.getClient(), this.spOpcUaClient.getSpOpcConfig());
+            this.allNodes = browserClient.findNodes(deleteKeys);
 
 
-                for (OpcNode node : this.allNodes) {
-                    this.allNodeIds.add(node.nodeId);
-                }
+            for (OpcNode node : this.allNodes) {
+                this.allNodeIds.add(node.nodeId);
+            }
 
             if (spOpcUaClient.inPullMode()) {
                 this.pullingIntervalMilliSeconds = spOpcUaClient.getPullIntervalMilliSeconds();
@@ -92,13 +114,15 @@
                 this.spOpcUaClient.createListSubscription(this.allNodeIds, this);
             }
 
+            this.allNodes.forEach(node -> this.nodeIdToLabelMapping.put(node.getNodeId().toString(), node.getLabel()));
+
 
         } catch (Exception e) {
-            throw new AdapterException("The Connection to the OPC UA server could not be established.");
+            throw new AdapterException("The Connection to the OPC UA server could not be established.", e.getCause());
         }
     }
 
-        @Override
+    @Override
     public void startAdapter() throws AdapterException {
 
         this.spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(this.adapterDescription));
@@ -115,49 +139,67 @@
         // close connection
         this.spOpcUaClient.disconnect();
 
-        if (this.spOpcUaClient.inPullMode()){
+        if (this.spOpcUaClient.inPullMode()) {
             super.stopAdapter();
         }
     }
 
     @Override
     protected void pullData() {
-        CompletableFuture<List<DataValue>> response = this.spOpcUaClient.getClient().readValues(0, TimestampsToReturn.Both, this.allNodeIds);
+        var response =
+          this.spOpcUaClient.getClient().readValues(0, TimestampsToReturn.Both, this.allNodeIds);
+        boolean badStatusCodeReceived = false;
+        boolean emptyValueReceived = false;
         try {
-        List<DataValue> returnValues = response.get();
-            for (int i = 0; i<returnValues.size(); i++) {
-
-                Object value = returnValues.get(i).getValue().getValue();
-                this.event.put(this.allNodes.get(i).getLabel(), value);
-
+            List<DataValue> returnValues = response.get(this.getPollingInterval().getValue(), this.getPollingInterval().getTimeUnit());
+            if (returnValues.size() == 0) {
+                emptyValueReceived = true;
+                LOG.warn("Empty value object returned - event will not be sent");
+            } else {
+                for (int i = 0; i < returnValues.size(); i++) {
+                    var status = returnValues.get(i).getStatusCode();
+                    if (StatusCode.GOOD.equals(status)) {
+                        Object value = returnValues.get(i).getValue().getValue();
+                        this.event.put(this.allNodes.get(i).getLabel(), value);
+                    } else {
+                        badStatusCodeReceived = true;
+                        LOG.warn("Received status code {} for node label: {} - event will not be sent",
+                                status,
+                                this.allNodes.get(i).getLabel());
+                    }
+                }
             }
-         } catch (InterruptedException | ExecutionException ie) {
-            ie.printStackTrace();
-         }
-
-        adapterPipeline.process(this.event);
-
+            if (!badStatusCodeReceived && !emptyValueReceived) {
+                adapterPipeline.process(this.event);
+            }
+        } catch (InterruptedException | ExecutionException | TimeoutException ie) {
+            LOG.error("Exception while reading data", ie);
+        }
     }
 
     public void onSubscriptionValue(UaMonitoredItem item, DataValue value) {
 
-        String key = OpcUaUtil.getRuntimeNameOfNode(item.getReadValueId().getNodeId());
+        String key = this.nodeIdToLabelMapping.get(item.getReadValueId().getNodeId().toString());
 
         OpcNode currNode = this.allNodes.stream()
-                .filter(node -> key.equals(node.getNodeId().getIdentifier().toString()))
+                .filter(node -> key.equals(node.getLabel()))
                 .findFirst()
                 .orElse(null);
 
-        event.put(currNode.getLabel(), value.getValue().getValue());
+        if (currNode != null) {
+            event.put(currNode.getLabel(), value.getValue().getValue());
 
-        // ensure that event is complete and all opc ua subscriptions transmitted at least one value
-        if (event.keySet().size() >= this.numberProperties) {
-            Map <String, Object> newEvent = new HashMap<>();
-            // deep copy of event to prevent preprocessor error
-            for (String k : event.keySet()) {
-                newEvent.put(k, event.get(k));
+            // ensure that event is complete and all opc ua subscriptions transmitted at least one value
+            if (event.keySet().size() >= this.numberProperties) {
+                Map<String, Object> newEvent = new HashMap<>();
+                // deep copy of event to prevent preprocessor error
+                for (String k : event.keySet()) {
+                    newEvent.put(k, event.get(k));
+                }
+                adapterPipeline.process(newEvent);
             }
-            adapterPipeline.process(newEvent);
+        } else {
+           LOG.error("No event is produced, because subscription item {} could not be found within all nodes", item);
         }
     }
 
@@ -176,27 +218,32 @@
                 .category(AdapterType.Generic, AdapterType.Manufacturing)
                 .requiredAlternatives(Labels.withId(OpcUaLabels.ADAPTER_TYPE.name()),
                         Alternatives.from(Labels.withId(OpcUaLabels.PULL_MODE.name()),
-                                StaticProperties.integerFreeTextProperty(Labels.withId(OpcUaLabels.PULLING_INTERVAL.name()))),
+                                StaticProperties.integerFreeTextProperty(
+                                        Labels.withId(OpcUaLabels.PULLING_INTERVAL.name()))),
                         Alternatives.from(Labels.withId(OpcUaLabels.SUBSCRIPTION_MODE.name())))
                 .requiredAlternatives(Labels.withId(OpcUaLabels.ACCESS_MODE.name()),
                         Alternatives.from(Labels.withId(OpcUaLabels.UNAUTHENTICATED.name())),
                         Alternatives.from(Labels.withId(OpcUaLabels.USERNAME_GROUP.name()),
                                 StaticProperties.group(
                                         Labels.withId(OpcUaLabels.USERNAME_GROUP.name()),
-                                        StaticProperties.stringFreeTextProperty(Labels.withId(OpcUaLabels.USERNAME.name())),
+                                        StaticProperties.stringFreeTextProperty(
+                                                Labels.withId(OpcUaLabels.USERNAME.name())),
                                         StaticProperties.secretValue(Labels.withId(OpcUaLabels.PASSWORD.name()))
                                 ))
                 )
                 .requiredAlternatives(Labels.withId(OpcUaLabels.OPC_HOST_OR_URL.name()),
                         Alternatives.from(
                                 Labels.withId(OpcUaLabels.OPC_URL.name()),
-                                StaticProperties.stringFreeTextProperty(Labels.withId(OpcUaLabels.OPC_SERVER_URL.name())))
+                                StaticProperties.stringFreeTextProperty(
+                                        Labels.withId(OpcUaLabels.OPC_SERVER_URL.name()), "opc.tcp://localhost:4840"))
                         ,
                         Alternatives.from(Labels.withId(OpcUaLabels.OPC_HOST.name()),
                                 StaticProperties.group(
                                         Labels.withId("host-port"),
-                                        StaticProperties.stringFreeTextProperty(Labels.withId(OpcUaLabels.OPC_SERVER_HOST.name())),
-                                        StaticProperties.stringFreeTextProperty(Labels.withId(OpcUaLabels.OPC_SERVER_PORT.name()))
+                                        StaticProperties.stringFreeTextProperty(
+                                                Labels.withId(OpcUaLabels.OPC_SERVER_HOST.name())),
+                                        StaticProperties.stringFreeTextProperty(
+                                                Labels.withId(OpcUaLabels.OPC_SERVER_PORT.name()))
                                 ))
                 )
                 .requiredTextParameter(Labels.withId(OpcUaLabels.NAMESPACE_INDEX.name()))
@@ -218,7 +265,8 @@
     }
 
     @Override
-    public GuessSchema getSchema(SpecificAdapterStreamDescription adapterDescription) throws AdapterException, ParseException {
+    public GuessSchema getSchema(SpecificAdapterStreamDescription adapterDescription)
+            throws AdapterException, ParseException {
         return OpcUaUtil.getSchema(adapterDescription);
     }
 
@@ -228,7 +276,8 @@
     }
 
     @Override
-    public StaticProperty resolveConfiguration(String staticPropertyInternalName, StaticPropertyExtractor extractor) {
+    public StaticProperty resolveConfiguration(String staticPropertyInternalName,
+                                               StaticPropertyExtractor extractor) throws SpConfigurationException {
         return OpcUaUtil.resolveConfiguration(staticPropertyInternalName, extractor);
     }
 }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaNodeBrowser.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaNodeBrowser.java
index 5a9f2fb..c1cbc20 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaNodeBrowser.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaNodeBrowser.java
@@ -23,13 +23,15 @@
 import org.apache.streampipes.model.staticproperty.TreeInputNode;
 import org.eclipse.milo.opcua.sdk.client.AddressSpace;
 import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
-import org.eclipse.milo.opcua.sdk.client.model.nodes.variables.BaseDataVariableTypeNode;
 import org.eclipse.milo.opcua.sdk.client.nodes.UaNode;
+import org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode;
 import org.eclipse.milo.opcua.stack.core.UaException;
 import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
 import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
 import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
 import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -43,21 +45,30 @@
   private final OpcUaClient client;
   private final SpOpcUaConfig spOpcConfig;
 
+  private static final Logger LOG = LoggerFactory.getLogger(OpcUaNodeBrowser.class);
+
   public OpcUaNodeBrowser(OpcUaClient client,
                           SpOpcUaConfig spOpcUaClientConfig) {
     this.client = client;
     this.spOpcConfig = spOpcUaClientConfig;
   }
 
-  public List<OpcNode> findNodes() {
-    return this.spOpcConfig.getSelectedNodeNames().stream().map(n -> {
-      try {
-        return toOpcNode(n);
-      } catch (UaException e) {
-        e.printStackTrace();
-        return null;
-      }
-    }).collect(Collectors.toList());
+  public List<OpcNode> findNodes() throws UaException {
+    var opcNodes = new ArrayList<OpcNode>();
+    for(String selectedNodeName: this.spOpcConfig.getSelectedNodeNames()) {
+      opcNodes.add(toOpcNode(selectedNodeName));
+    }
+
+    return opcNodes;
+  }
+
+  public List<OpcNode> findNodes(List<String> runtimeNameFilters) throws UaException {
+    return findNodes()
+      .stream()
+      .filter(node -> runtimeNameFilters
+        .stream()
+        .noneMatch(f -> f.equals(node.getLabel())))
+      .collect(Collectors.toList());
   }
 
   public List<TreeInputNode> buildNodeTreeFromOrigin() throws UaException, ExecutionException, InterruptedException {
@@ -80,11 +91,15 @@
     NodeId nodeId = NodeId.parse(nodeName);
     UaNode node = addressSpace.getNode(nodeId);
 
-    if (node instanceof BaseDataVariableTypeNode) {
-      UInteger value = (UInteger) ((BaseDataVariableTypeNode) node).getDataType().getIdentifier();
+    LOG.info("Using node of type {}", node.getNodeClass().toString() );
+
+    if (node instanceof UaVariableNode) {
+      UInteger value = (UInteger) ((UaVariableNode) node).getDataType().getIdentifier();
       return new OpcNode(node.getDisplayName().getText(), OpcUaTypes.getType(value), node.getNodeId());
     }
 
+    LOG.warn("Node {} not of type UaVariableNode", node.getDisplayName());
+
     throw new UaException(StatusCode.BAD, "Node is not of type BaseDataVariableTypeNode");
   }
 
@@ -112,6 +127,6 @@
   }
 
   private boolean isDataNode(UaNode node) {
-    return node.getNodeClass().equals(NodeClass.Variable) && node instanceof BaseDataVariableTypeNode;
+    return (node.getNodeClass().equals(NodeClass.Variable) || (node.getNodeClass().equals(NodeClass.VariableType))) && node instanceof UaVariableNode;
   }
 }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/SpOpcUaClient.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/SpOpcUaClient.java
index da00cbf..299c4f0 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/SpOpcUaClient.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/SpOpcUaClient.java
@@ -19,15 +19,19 @@
 package org.apache.streampipes.connect.iiot.adapters.opcua;
 
 
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.connect.iiot.adapters.opcua.configuration.SpOpcUaConfig;
 import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
 import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
 import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem;
 import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription;
+import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscriptionManager;
 import org.eclipse.milo.opcua.stack.core.AttributeId;
+import org.eclipse.milo.opcua.stack.core.UaException;
 import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
 import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
 import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName;
+import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
 import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
 import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode;
 import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
@@ -37,9 +41,11 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicLong;
 
 import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
@@ -71,9 +77,9 @@
     /***
      * Establishes appropriate connection to OPC UA endpoint depending on the {@link SpOpcUaClient} instance
      *
-     * @throws Exception An exception occurring during OPC connection
+     * @throws UaException An exception occurring during OPC connection
      */
-    public void connect() throws Exception {
+    public void connect() throws UaException, ExecutionException, InterruptedException, SpConfigurationException, URISyntaxException {
         OpcUaClientConfig clientConfig = new MiloOpcUaConfigurationProvider().makeClientConfig(spOpcConfig);
         this.client = OpcUaClient.create(clientConfig);
         client.connect().get();
@@ -89,7 +95,25 @@
      * @param opcUaAdapter current instance of {@link OpcUaAdapter}
      * @throws Exception
      */
-    public void createListSubscription(List<NodeId> nodes, OpcUaAdapter opcUaAdapter) throws Exception {
+    public void createListSubscription(List<NodeId> nodes,
+                                       OpcUaAdapter opcUaAdapter) throws Exception {
+        client.getSubscriptionManager().addSubscriptionListener(new UaSubscriptionManager.SubscriptionListener() {
+            @Override
+            public void onSubscriptionTransferFailed(UaSubscription subscription, StatusCode statusCode) {
+                LOG.warn("Transfer for subscriptionId={} failed: {}", subscription.getSubscriptionId(), statusCode);
+                try {
+                    initSubscription(nodes, opcUaAdapter);
+                } catch (Exception e) {
+                    LOG.error("Re-creating the subscription failed", e);
+                }
+            }
+        });
+
+        initSubscription(nodes, opcUaAdapter);
+    }
+
+
+    public void initSubscription(List<NodeId> nodes, OpcUaAdapter opcUaAdapter) throws Exception {
         /*
          * create a subscription @ 1000ms
          */
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/ExceptionMessageExtractor.java
similarity index 62%
copy from ui/src/app/connect/components/format-item-json/format-item-json.component.scss
copy to streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/ExceptionMessageExtractor.java
index 30123c0..7c1b453 100644
--- a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/ExceptionMessageExtractor.java
@@ -16,32 +16,23 @@
  *
  */
 
+package org.apache.streampipes.connect.iiot.adapters.opcua.utils;
 
-.format-label {
-  line-height:50px;
-  margin: auto;
-  text-align: center;
-  font-weight: bold;
-  font-size: 1.3em;
+import org.eclipse.milo.opcua.stack.core.UaException;
+
+public class ExceptionMessageExtractor {
+
+  public static String getDescription(UaException e) {
+    String[] parts = e.getMessage().split(", ");
+    if (parts.length > 1) {
+      String[] kv = parts[1].split("=");
+      if (kv.length > 1) {
+        return kv[1];
+      } else {
+        return parts[1];
+      }
+    } else {
+      return e.getMessage();
+    }
+  }
 }
-
-.format-box {
-  min-height: 50px;
-  box-shadow: 1px 1px 2px #555;
-  border: 1px solid gray;
-  cursor: pointer;
-  padding: 10px;
-  opacity: 0.7;
-  margin: 10px;
-  background: #ffffff;
-}
-
-.format-box:hover {
-  opacity: 1;
-}
-
-.selectedItem {
-  opacity: 1;
-  background-color: grey;
-}
-
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
index 38d4d4c..739dc19 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.connect.iiot.adapters.opcua.utils;
 
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.connect.iiot.adapters.opcua.OpcNode;
@@ -25,7 +26,9 @@
 import org.apache.streampipes.connect.iiot.adapters.opcua.SpOpcUaClient;
 import org.apache.streampipes.connect.iiot.adapters.opcua.configuration.SpOpcUaConfigBuilder;
 import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
+import org.apache.streampipes.model.connect.guess.FieldStatusInfo;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.connect.guess.GuessTypeInfo;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.model.staticproperty.RuntimeResolvableTreeInputStaticProperty;
@@ -33,165 +36,220 @@
 import org.apache.streampipes.sdk.extractor.StaticPropertyExtractor;
 import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
 import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
 import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
 import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
 
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
 
 /***
  * Collection of several utility functions in context of OPC UA
  */
 public class OpcUaUtil {
 
-    /***
-     * Ensures server address starts with {@code opc.tcp://}
-     * @param serverAddress server address as given by user
-     * @return correctly formated server address
-     */
-    public static String formatServerAddress(String serverAddress) {
+  /***
+   * Ensures server address starts with {@code opc.tcp://}
+   * @param serverAddress server address as given by user
+   * @return correctly formated server address
+   */
+  public static String formatServerAddress(String serverAddress) {
 
-        if (!serverAddress.startsWith("opc.tcp://")) {
-            serverAddress = "opc.tcp://" + serverAddress;
-        }
-
-        return serverAddress;
+    if (!serverAddress.startsWith("opc.tcp://")) {
+      serverAddress = "opc.tcp://" + serverAddress;
     }
 
-    /***
-     * OPC UA specific implementation of {@link org.apache.streampipes.connect.adapter.Adapter}
-     * @param adapterStreamDescription
-     * @return guess schema
-     * @throws AdapterException
-     * @throws ParseException
-     */
-    public static GuessSchema getSchema(SpecificAdapterStreamDescription adapterStreamDescription) throws AdapterException, ParseException {
-        GuessSchema guessSchema = new GuessSchema();
-        EventSchema eventSchema = new EventSchema();
-        List<EventProperty> allProperties = new ArrayList<>();
+    return serverAddress;
+  }
 
-        SpOpcUaClient spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(adapterStreamDescription));
+  /***
+   * OPC UA specific implementation of {@link org.apache.streampipes.connect.adapter.Adapter}
+   * @param adapterStreamDescription
+   * @return guess schema
+   * @throws AdapterException
+   * @throws ParseException
+   */
+  public static GuessSchema getSchema(SpecificAdapterStreamDescription adapterStreamDescription)
+    throws AdapterException, ParseException {
+    GuessSchema guessSchema = new GuessSchema();
+    EventSchema eventSchema = new EventSchema();
+    List<Map<String, GuessTypeInfo>> eventPreview = new ArrayList<>();
+    Map<String, FieldStatusInfo> fieldStatusInfos = new HashMap<>();
+    List<EventProperty> allProperties = new ArrayList<>();
 
-        try {
-            spOpcUaClient.connect();
-            OpcUaNodeBrowser nodeBrowser = new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
-            List<OpcNode> selectedNodes = nodeBrowser.findNodes();
+    SpOpcUaClient spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(adapterStreamDescription));
 
-            if (!selectedNodes.isEmpty()) {
-                for (OpcNode opcNode : selectedNodes) {
-                    if (opcNode.hasUnitId()) {
-                        allProperties.add(PrimitivePropertyBuilder
-                            .create(opcNode.getType(), opcNode.getLabel())
-                            .label(opcNode.getLabel())
-                            .measurementUnit(new URI(opcNode.getQudtURI()))
-                            .build());
-                    } else {
-                        allProperties.add(PrimitivePropertyBuilder
-                            .create(opcNode.getType(), opcNode.getLabel())
-                            .label(opcNode.getLabel())
-                            .build());
-                    }
+    try {
+      spOpcUaClient.connect();
+      OpcUaNodeBrowser nodeBrowser =
+        new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
+      List<OpcNode> selectedNodes = nodeBrowser.findNodes();
 
-                }
-            }
-
-            spOpcUaClient.disconnect();
-
-        } catch (Exception e) {
-            throw new AdapterException("Could not guess schema for opc node! " + e.getMessage());
+      if (!selectedNodes.isEmpty()) {
+        for (OpcNode opcNode : selectedNodes) {
+          if (opcNode.hasUnitId()) {
+            allProperties.add(PrimitivePropertyBuilder
+              .create(opcNode.getType(), opcNode.getLabel())
+              .label(opcNode.getLabel())
+              .measurementUnit(new URI(opcNode.getQudtURI()))
+              .build());
+          } else {
+            allProperties.add(PrimitivePropertyBuilder
+              .create(opcNode.getType(), opcNode.getLabel())
+              .label(opcNode.getLabel())
+              .build());
+          }
         }
+      }
 
-        eventSchema.setEventProperties(allProperties);
-        guessSchema.setEventSchema(eventSchema);
+      var nodeIds = selectedNodes.stream().map(OpcNode::getNodeId).collect(Collectors.toList());
+      var response = spOpcUaClient.getClient().readValues(0, TimestampsToReturn.Both, nodeIds);
 
-        return guessSchema;
+      var returnValues = response.get();
+
+      makeEventPreview(selectedNodes, eventPreview, fieldStatusInfos, returnValues);
+
+
+    } catch (Exception e) {
+      throw new AdapterException("Could not guess schema for opc node:  " + e.getMessage(), e);
+    } finally {
+      spOpcUaClient.disconnect();
     }
 
+    eventSchema.setEventProperties(allProperties);
+    guessSchema.setEventSchema(eventSchema);
+    guessSchema.setEventPreview(eventPreview);
+    guessSchema.setFieldStatusInfo(fieldStatusInfos);
 
-    /***
-     * OPC UA specific implementation of {@link org.apache.streampipes.container.api.ResolvesContainerProvidedOptions#resolveOptions(String, StaticPropertyExtractor)}.  }
-     * @param internalName The internal name of the Static Property
-     * @param parameterExtractor
-     * @return {@code List<Option>} with available node names for the given OPC UA configuration
-     */
-    public static RuntimeResolvableTreeInputStaticProperty resolveConfiguration (String internalName,
-                                                                                 StaticPropertyExtractor parameterExtractor) {
+    return guessSchema;
+  }
 
-        RuntimeResolvableTreeInputStaticProperty config = parameterExtractor
-                .getStaticPropertyByName(internalName, RuntimeResolvableTreeInputStaticProperty.class);
-        // access mode and host/url have to be selected
-        try {
-            parameterExtractor.selectedAlternativeInternalId(OpcUaLabels.OPC_HOST_OR_URL.name());
-            parameterExtractor.selectedAlternativeInternalId(OpcUaLabels.ACCESS_MODE.name());
-        } catch (NullPointerException nullPointerException) {
-            return config;
-        }
+  private static void makeEventPreview(List<OpcNode> selectedNodes,
+                                       List<Map<String, GuessTypeInfo>> eventPreview,
+                                       Map<String, FieldStatusInfo> fieldStatusInfos,
+                                       List<DataValue> dataValues) {
+    var singlePreview = new HashMap<String, GuessTypeInfo>();
 
-        SpOpcUaClient spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(parameterExtractor));
-        try{
-            spOpcUaClient.connect();
-            OpcUaNodeBrowser nodeBrowser = new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
-            config.setNodes(nodeBrowser.buildNodeTreeFromOrigin());
-            spOpcUaClient.disconnect();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-
-        return config;
+    for (int i = 0; i < dataValues.size(); i++) {
+      var dv = dataValues.get(i);
+      String label = selectedNodes.get(i).getLabel();
+      if (StatusCode.GOOD.equals(dv.getStatusCode())) {
+        var value = dv.getValue().getValue();
+        singlePreview.put(label, new GuessTypeInfo(value.getClass().getCanonicalName(), value));
+        fieldStatusInfos.put(label, FieldStatusInfo.good());
+      } else {
+        String additionalInfo = dv.getStatusCode() != null ? dv.getStatusCode().toString() : "Status code is null";
+        fieldStatusInfos.put(label, FieldStatusInfo.bad(additionalInfo, false));
+      }
     }
 
-    public static String getRuntimeNameOfNode(NodeId nodeId) {
-        String[] keys = nodeId.getIdentifier().toString().split("\\.");
-        String key;
+    eventPreview.add(singlePreview);
+  }
 
-        if (keys.length > 0) {
-            key = keys[keys.length - 1];
-        } else {
-            key = nodeId.getIdentifier().toString();
-        }
 
-        return key;
+  /***
+   * OPC UA specific implementation of {@link
+   * org.apache.streampipes.container.api.ResolvesContainerProvidedOptions#
+   * resolveOptions(String, StaticPropertyExtractor)}.
+   * @param internalName The internal name of the Static Property
+   * @param parameterExtractor to extract parameters from the OPC UA config
+   * @return {@code List<Option>} with available node names for the given OPC UA configuration
+   */
+  public static RuntimeResolvableTreeInputStaticProperty resolveConfiguration(String internalName,
+                                                                              StaticPropertyExtractor parameterExtractor) throws SpConfigurationException {
+
+    RuntimeResolvableTreeInputStaticProperty config = parameterExtractor
+      .getStaticPropertyByName(internalName, RuntimeResolvableTreeInputStaticProperty.class);
+    // access mode and host/url have to be selected
+    try {
+      parameterExtractor.selectedAlternativeInternalId(OpcUaLabels.OPC_HOST_OR_URL.name());
+      parameterExtractor.selectedAlternativeInternalId(OpcUaLabels.ACCESS_MODE.name());
+    } catch (NullPointerException nullPointerException) {
+      return config;
     }
 
-    /**
-     * connects to each node individually and updates the data type in accordance to the data from the server.
-     * @param opcNodes List of opcNodes where the data type is not determined appropriately
-     */
-    public static void retrieveDataTypesFromServer(OpcUaClient client, List<OpcNode> opcNodes) throws AdapterException {
+    SpOpcUaClient spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(parameterExtractor));
 
-        for (OpcNode opcNode : opcNodes) {
-            try {
-                UInteger dataTypeId = (UInteger) client.getAddressSpace().getVariableNode(opcNode.getNodeId()).getDataType().getIdentifier();
-                OpcUaTypes.getType(dataTypeId);
-                opcNode.setType(OpcUaTypes.getType(dataTypeId));
-            } catch (UaException e) {
-               throw new AdapterException("Could not guess schema for opc node! " + e.getMessage());
-            }
-        }
+    try {
+      spOpcUaClient.connect();
+      OpcUaNodeBrowser nodeBrowser =
+        new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
+      config.setNodes(nodeBrowser.buildNodeTreeFromOrigin());
+
+      return config;
+    } catch (UaException e) {
+      throw new SpConfigurationException(ExceptionMessageExtractor.getDescription(e), e);
+    } catch (ExecutionException | InterruptedException | URISyntaxException e) {
+      throw new SpConfigurationException("Could not connect to the OPC UA server with the provided settings", e);
+    } finally {
+      if (spOpcUaClient.getClient() != null) {
+        spOpcUaClient.disconnect();
+      }
+    }
+  }
+
+  public static String getRuntimeNameOfNode(NodeId nodeId) {
+    String[] keys = nodeId.getIdentifier().toString().split("\\.");
+    String key;
+
+    if (keys.length > 0) {
+      key = keys[keys.length - 1];
+    } else {
+      key = nodeId.getIdentifier().toString();
     }
 
-    /***
-     * Enum for all possible labels in the context of OPC UA adapters
-     */
-    public enum OpcUaLabels {
-        OPC_HOST_OR_URL,
-        OPC_URL,
-        OPC_HOST,
-        OPC_SERVER_URL,
-        OPC_SERVER_HOST,
-        OPC_SERVER_PORT,
-        NAMESPACE_INDEX,
-        NODE_ID,
-        ACCESS_MODE,
-        USERNAME_GROUP,
-        USERNAME,
-        PASSWORD,
-        UNAUTHENTICATED,
-        AVAILABLE_NODES,
-        PULLING_INTERVAL,
-        ADAPTER_TYPE,
-        PULL_MODE,
-        SUBSCRIPTION_MODE;
+    return key;
+  }
+
+  /**
+   * connects to each node individually and updates the data type in accordance to the data from the server.
+   *
+   * @param opcNodes List of opcNodes where the data type is not determined appropriately
+   */
+  public static void retrieveDataTypesFromServer(OpcUaClient client, List<OpcNode> opcNodes) throws AdapterException {
+
+    for (OpcNode opcNode : opcNodes) {
+      try {
+        UInteger dataTypeId =
+          (UInteger) client.getAddressSpace().getVariableNode(opcNode.getNodeId()).getDataType()
+            .getIdentifier();
+        OpcUaTypes.getType(dataTypeId);
+        opcNode.setType(OpcUaTypes.getType(dataTypeId));
+      } catch (UaException e) {
+        throw new AdapterException("Could not guess schema for opc node! " + e.getMessage());
+      }
     }
+  }
+
+  /***
+   * Enum for all possible labels in the context of OPC UA adapters
+   */
+  public enum OpcUaLabels {
+    OPC_HOST_OR_URL,
+    OPC_URL,
+    OPC_HOST,
+    OPC_SERVER_URL,
+    OPC_SERVER_HOST,
+    OPC_SERVER_PORT,
+    NAMESPACE_INDEX,
+    NODE_ID,
+    ACCESS_MODE,
+    USERNAME_GROUP,
+    USERNAME,
+    PASSWORD,
+    UNAUTHENTICATED,
+    AVAILABLE_NODES,
+    PULLING_INTERVAL,
+    ADAPTER_TYPE,
+    PULL_MODE,
+    SUBSCRIPTION_MODE;
+  }
 }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/Plc4xS7Adapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/Plc4xS7Adapter.java
index 04ece8a..227054b 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/Plc4xS7Adapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/Plc4xS7Adapter.java
@@ -27,11 +27,12 @@
 import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
 import org.apache.streampipes.connect.adapter.Adapter;
 import org.apache.streampipes.connect.adapter.util.PollingSettings;
-import org.apache.streampipes.connect.iiot.adapters.PullAdapter;
 import org.apache.streampipes.connect.api.exception.AdapterException;
+import org.apache.streampipes.connect.iiot.adapters.PullAdapter;
 import org.apache.streampipes.model.AdapterType;
 import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.connect.guess.GuessTypeInfo;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.model.staticproperty.CollectionStaticProperty;
@@ -54,10 +55,10 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
-public class Plc4xS7Adapter extends PullAdapter {
+public class Plc4xS7Adapter extends PullAdapter implements PlcReadResponseHandler {
 
     /**
      * A unique id to identify the Plc4xS7Adapter
@@ -133,31 +134,45 @@
     public GuessSchema getSchema(SpecificAdapterStreamDescription adapterDescription) throws AdapterException {
 
         // Extract user input
-        getConfigurations(adapterDescription);
+        try {
+            getConfigurations(adapterDescription);
 
-        if (this.pollingInterval < 10) {
-            throw new AdapterException("Polling interval must be higher then 10. Current value: " + this.pollingInterval);
+            if (this.pollingInterval < 10) {
+                throw new AdapterException("Polling interval must be higher than 10. Current value: " + this.pollingInterval);
+            }
+
+            GuessSchema guessSchema = new GuessSchema();
+
+            EventSchema eventSchema = new EventSchema();
+            List<EventProperty> allProperties = new ArrayList<>();
+
+            for (Map<String, String> node : this.nodes) {
+                Datatypes datatype = getStreamPipesDataType(node.get(PLC_NODE_TYPE).toUpperCase().replaceAll(" ", "_"));
+
+                allProperties.add(
+                  PrimitivePropertyBuilder
+                    .create(datatype, node.get(PLC_NODE_RUNTIME_NAME))
+                    .label(node.get(PLC_NODE_RUNTIME_NAME))
+                    .description("")
+                    .build());
+            }
+
+            this.before();
+            var event = readPlcDataSynchronized();
+            var preview = event
+              .entrySet()
+              .stream()
+              .collect(Collectors.toMap(Map.Entry::getKey, e ->
+                new GuessTypeInfo(e.getValue().getClass().getCanonicalName(), e.getValue())));
+
+            eventSchema.setEventProperties(allProperties);
+            guessSchema.setEventSchema(eventSchema);
+            guessSchema.setEventPreview(List.of(preview));
+
+            return guessSchema;
+        } catch (Exception e) {
+            throw new AdapterException(e.getMessage(), e);
         }
-
-        GuessSchema guessSchema = new GuessSchema();
-
-        EventSchema eventSchema = new EventSchema();
-        List<EventProperty> allProperties = new ArrayList<>();
-
-        for (Map<String, String> node : this.nodes) {
-            Datatypes datatype = getStreamPipesDataType(node.get(PLC_NODE_TYPE).toUpperCase().replaceAll(" ", "_"));
-
-            allProperties.add(
-                    PrimitivePropertyBuilder
-                            .create(datatype, node.get(PLC_NODE_RUNTIME_NAME))
-                            .label(node.get(PLC_NODE_RUNTIME_NAME))
-                            .description("")
-                            .build());
-        }
-
-        eventSchema.setEventProperties(allProperties);
-        guessSchema.setEventSchema(eventSchema);
-        return guessSchema;
     }
 
     /**
@@ -171,7 +186,6 @@
 
         this.driverManager = new PooledPlcDriverManager();
         try (PlcConnection plcConnection = this.driverManager.getConnection("s7://" + this.ip)) {
-
             if (!plcConnection.getMetadata().canRead()) {
                 this.LOG.error("The S7 on IP: " + this.ip + " does not support reading data");
             }
@@ -188,47 +202,36 @@
      */
     @Override
     protected void pullData() {
-
         // Create PLC read request
-        try (PlcConnection plcConnection = this.driverManager.getConnection("s7://" + this.ip)) {
-            PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
-            for (Map<String, String> node : this.nodes) {
-                builder.addItem(node.get(PLC_NODE_NAME), node.get(PLC_NODE_NAME) + ":" + node.get(PLC_NODE_TYPE).toUpperCase().replaceAll(" ", "_"));
-            }
-            PlcReadRequest readRequest = builder.build();
-
-            // Execute the request
-            CompletableFuture<? extends PlcReadResponse> asyncResponse = readRequest.execute();
-
-            asyncResponse.whenComplete((response, throwable) -> {
-                // Create an event containing the value of the PLC
-                if (throwable != null) {
-                    throwable.printStackTrace();
-                    this.LOG.error(throwable.getMessage());
-                } else {
-                    Map<String, Object> event = new HashMap<>();
-                    for (Map<String, String> node : this.nodes) {
-                        if (response.getResponseCode(node.get(PLC_NODE_NAME)) == PlcResponseCode.OK) {
-                            event.put(node.get(PLC_NODE_RUNTIME_NAME), response.getObject(node.get(PLC_NODE_NAME)));
-                        } else {
-                            this.LOG.error("Error[" + node.get(PLC_NODE_NAME) + "]: " +
-                                    response.getResponseCode(node.get(PLC_NODE_NAME)).name());
-                        }
-                    }
-
-                    // publish the final event
-                    adapterPipeline.process(event);
-                }
-            });
-
-        } catch (InterruptedException | ExecutionException e) {
-            this.LOG.error(e.getMessage());
-            e.printStackTrace();
+        try(PlcConnection plcConnection = this.driverManager.getConnection("s7://" + this.ip)) {
+            readPlcData(plcConnection, this);
         } catch (Exception e) {
-            this.LOG.error("Could not establish connection to S7 with ip " + this.ip, e);
-            e.printStackTrace();
+            LOG.error("Error while reading from PLC with IP {} ", this.ip, e);
         }
+    }
 
+    private PlcReadRequest makeReadRequest(PlcConnection plcConnection) throws PlcConnectionException {
+        PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
+        for (Map<String, String> node : this.nodes) {
+            builder.addItem(node.get(PLC_NODE_NAME), node.get(PLC_NODE_NAME) + ":" + node.get(PLC_NODE_TYPE).toUpperCase().replaceAll(" ", "_"));
+        }
+        return builder.build();
+    }
+
+    private void readPlcData(PlcConnection plcConnection, PlcReadResponseHandler handler) throws PlcConnectionException {
+        var readRequest = makeReadRequest(plcConnection);
+        // Execute the request
+        CompletableFuture<? extends PlcReadResponse> asyncResponse = readRequest.execute();
+        asyncResponse.whenComplete(handler::onReadResult);
+    }
+
+    private Map<String, Object> readPlcDataSynchronized() throws Exception {
+        try (PlcConnection plcConnection = this.driverManager.getConnection("s7://" + this.ip)) {
+            var readRequest = makeReadRequest(plcConnection);
+            // Execute the request
+            var readResponse = readRequest.execute().get(5000, TimeUnit.MILLISECONDS);
+            return makeEvent(readResponse);
+        }
     }
 
     /**
@@ -315,4 +318,28 @@
         }
     }
 
+    @Override
+    public void onReadResult(PlcReadResponse response, Throwable throwable) {
+        if (throwable != null) {
+            throwable.printStackTrace();
+            this.LOG.error(throwable.getMessage());
+        } else {
+            var event = makeEvent(response);
+            // publish the final event
+            adapterPipeline.process(event);
+        }
+    }
+
+    private Map<String, Object> makeEvent(PlcReadResponse response) {
+        Map<String, Object> event = new HashMap<>();
+        for (Map<String, String> node : this.nodes) {
+            if (response.getResponseCode(node.get(PLC_NODE_NAME)) == PlcResponseCode.OK) {
+                event.put(node.get(PLC_NODE_RUNTIME_NAME), response.getObject(node.get(PLC_NODE_NAME)));
+            } else {
+                this.LOG.error("Error[" + node.get(PLC_NODE_NAME) + "]: " +
+                  response.getResponseCode(node.get(PLC_NODE_NAME)).name());
+            }
+        }
+        return event;
+    }
 }
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/PlcReadResponseHandler.java
similarity index 75%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/PlcReadResponseHandler.java
index 58ba04b..b9b8f1b 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/plc4x/s7/PlcReadResponseHandler.java
@@ -16,3 +16,12 @@
  *
  */
 
+package org.apache.streampipes.connect.iiot.adapters.plc4x.s7;
+
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+
+public interface PlcReadResponseHandler {
+
+  void onReadResult(PlcReadResponse response,
+                    Throwable throwable);
+}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/simulator/machine/MachineDataSimulatorUtils.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/simulator/machine/MachineDataSimulatorUtils.java
index 0d7b2af..f157bab 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/simulator/machine/MachineDataSimulatorUtils.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/simulator/machine/MachineDataSimulatorUtils.java
@@ -30,123 +30,137 @@
 
 public class MachineDataSimulatorUtils {
 
-    // Vocabulary
-    public static final String NS = "https://streampipes.org/vocabulary/examples/watertank/v1/";
-    public static final String HAS_SENSOR_ID = NS + "hasSensorId";
+  // Vocabulary
+  public static final String NS = "https://streampipes.org/vocabulary/examples/watertank/v1/";
+  public static final String HAS_SENSOR_ID = NS + "hasSensorId";
 
-    private static final String TIMESTAMP = "timestamp";
-    private static final String SENSOR_ID = "sensorId";
-    private static final String MASS_FLOW = "mass_flow";
-    private static final String TEMPERATURE = "temperature";
+  private static final String TIMESTAMP = "timestamp";
+  private static final String SENSOR_ID = "sensorId";
+  private static final String MASS_FLOW = "mass_flow";
+  private static final String TEMPERATURE = "temperature";
 
-    public static GuessSchema getSchema(String selectedSimulatorOption) throws AdapterException {
-        switch(selectedSimulatorOption) {
-            case "flowrate":
-                return getFlowrateSchema();
-            case "pressure":
-                return getPressureSchema();
-            case "waterlevel":
-                return getWaterlevelSchema();
-            default:
-                throw new AdapterException("resource not found");
-        }
+  public static GuessSchema getSchema(String selectedSimulatorOption) throws AdapterException {
+    switch (selectedSimulatorOption) {
+      case "flowrate":
+        return getFlowrateSchema();
+      case "pressure":
+        return getPressureSchema();
+      case "waterlevel":
+        return getWaterlevelSchema();
+      default:
+        throw new AdapterException("resource not found");
     }
+  }
 
-    private static GuessSchema getWaterlevelSchema() {
-        return GuessSchemaBuilder.create()
-                .property(timestampProperty(TIMESTAMP))
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.String, "sensorId")
-                        .label("Sensor ID")
-                        .description("The ID of the sensor")
-                        .domainProperty(HAS_SENSOR_ID)
-                        .scope(PropertyScope.DIMENSION_PROPERTY)
-                        .build())
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.Float, "level")
-                        .label("Water Level")
-                        .description("Denotes the current water level in the container")
-                        .domainProperty(SO.Number)
-                        .scope(PropertyScope.MEASUREMENT_PROPERTY)
-                        .build())
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.Boolean, "overflow")
-                        .label("Overflow")
-                        .description("Indicates whether the tank overflows")
-                        .domainProperty(SO.Number)
-                        .scope(PropertyScope.MEASUREMENT_PROPERTY)
-                        .build())
-                .build();
-    }
+  private static GuessSchema getWaterlevelSchema() {
+    return GuessSchemaBuilder.create()
+      .property(timestampProperty(TIMESTAMP))
+      .sample(TIMESTAMP, System.currentTimeMillis())
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.String, "sensorId")
+        .label("Sensor ID")
+        .description("The ID of the sensor")
+        .domainProperty(HAS_SENSOR_ID)
+        .scope(PropertyScope.DIMENSION_PROPERTY)
+        .build())
+      .sample("sensorId", "sensor01")
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.Float, "level")
+        .label("Water Level")
+        .description("Denotes the current water level in the container")
+        .domainProperty(SO.Number)
+        .scope(PropertyScope.MEASUREMENT_PROPERTY)
+        .build())
+      .sample("level", 5.25f)
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.Boolean, "overflow")
+        .label("Overflow")
+        .description("Indicates whether the tank overflows")
+        .domainProperty(SO.Number)
+        .scope(PropertyScope.MEASUREMENT_PROPERTY)
+        .build())
+      .sample("overflow", true)
+      .build();
+  }
 
-    private static GuessSchema getPressureSchema() {
-        return GuessSchemaBuilder.create()
-                .property(timestampProperty(TIMESTAMP))
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.String, "sensorId")
-                        .label("Sensor ID")
-                        .description("The ID of the sensor")
-                        .domainProperty(HAS_SENSOR_ID)
-                        .scope(PropertyScope.DIMENSION_PROPERTY)
-                        .build())
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.Float, "pressure")
-                        .label("Pressure")
-                        .description("Denotes the current pressure in the pressure tank")
-                        .domainProperty(SO.Number)
-                        .valueSpecification(0.0f, 100.0f, 0.5f)
-                        .scope(PropertyScope.MEASUREMENT_PROPERTY)
-                        .build())
-                .build();
-    }
+  private static GuessSchema getPressureSchema() {
+    return GuessSchemaBuilder.create()
+      .property(timestampProperty(TIMESTAMP))
+      .sample(TIMESTAMP, System.currentTimeMillis())
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.String, "sensorId")
+        .label("Sensor ID")
+        .description("The ID of the sensor")
+        .domainProperty(HAS_SENSOR_ID)
+        .scope(PropertyScope.DIMENSION_PROPERTY)
+        .build())
+      .sample("sensorId", "sensor01")
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.Float, "pressure")
+        .label("Pressure")
+        .description("Denotes the current pressure in the pressure tank")
+        .domainProperty(SO.Number)
+        .valueSpecification(0.0f, 100.0f, 0.5f)
+        .scope(PropertyScope.MEASUREMENT_PROPERTY)
+        .build())
+      .sample("pressure", 85.22f)
+      .build();
+  }
 
-    public static GuessSchema getFlowrateSchema() {
-        return GuessSchemaBuilder.create()
-                .property(timestampProperty(TIMESTAMP))
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.String, SENSOR_ID)
-                        .label("Sensor ID")
-                        .description("The ID of the sensor")
-                        .domainProperty(HAS_SENSOR_ID)
-                        .scope(PropertyScope.DIMENSION_PROPERTY)
-                        .build())
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.Float, MASS_FLOW)
-                        .label("Mass Flow")
-                        .description("Denotes the current mass flow in the sensor")
-                        .domainProperty(SO.Number)
-                        .scope(PropertyScope.MEASUREMENT_PROPERTY)
-                        .build())
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.Float, "volume_flow")
-                        .label("Volume Flow")
-                        .description("Denotes the current volume flow")
-                        .domainProperty(SO.Number)
-                        .scope(PropertyScope.MEASUREMENT_PROPERTY)
-                        .build())
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.Float, TEMPERATURE)
-                        .label("Temperature")
-                        .description("Denotes the current temperature in degrees celsius")
-                        .domainProperty(SO.Number)
-                        .scope(PropertyScope.MEASUREMENT_PROPERTY)
-                        .measurementUnit(URI.create("http://codes.wmo.int/common/unit/degC"))
-                        .valueSpecification(0.0f, 100.0f, 0.1f)
-                        .build())
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.Float, "density")
-                        .label("Density")
-                        .description("Denotes the current density of the fluid")
-                        .domainProperty(SO.Number)
-                        .scope(PropertyScope.MEASUREMENT_PROPERTY)
-                        .build())
-                .property(PrimitivePropertyBuilder
-                        .create(Datatypes.Boolean, "sensor_fault_flags")
-                        .label("Sensor Fault Flags")
-                        .description("Any fault flags of the sensors")
-                        .domainProperty(SO.Boolean)
-                        .scope(PropertyScope.MEASUREMENT_PROPERTY)
-                        .build())
-                .build();
-    }
+  public static GuessSchema getFlowrateSchema() {
+    return GuessSchemaBuilder.create()
+      .property(timestampProperty(TIMESTAMP))
+      .sample(TIMESTAMP, System.currentTimeMillis())
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.String, SENSOR_ID)
+        .label("Sensor ID")
+        .description("The ID of the sensor")
+        .domainProperty(HAS_SENSOR_ID)
+        .scope(PropertyScope.DIMENSION_PROPERTY)
+        .build())
+      .sample("sensorId", "sensor01")
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.Float, MASS_FLOW)
+        .label("Mass Flow")
+        .description("Denotes the current mass flow in the sensor")
+        .domainProperty(SO.Number)
+        .scope(PropertyScope.MEASUREMENT_PROPERTY)
+        .build())
+      .sample(MASS_FLOW, 5.76f)
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.Float, "volume_flow")
+        .label("Volume Flow")
+        .description("Denotes the current volume flow")
+        .domainProperty(SO.Number)
+        .scope(PropertyScope.MEASUREMENT_PROPERTY)
+        .build())
+      .sample("volume_flow", 3.34f)
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.Float, TEMPERATURE)
+        .label("Temperature")
+        .description("Denotes the current temperature in degrees celsius")
+        .domainProperty(SO.Number)
+        .scope(PropertyScope.MEASUREMENT_PROPERTY)
+        .measurementUnit(URI.create("http://codes.wmo.int/common/unit/degC"))
+        .valueSpecification(0.0f, 100.0f, 0.1f)
+        .build())
+      .sample(TEMPERATURE, 33.221f)
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.Float, "density")
+        .label("Density")
+        .description("Denotes the current density of the fluid")
+        .domainProperty(SO.Number)
+        .scope(PropertyScope.MEASUREMENT_PROPERTY)
+        .build())
+      .sample("density", 5.0f)
+      .property(PrimitivePropertyBuilder
+        .create(Datatypes.Boolean, "sensor_fault_flags")
+        .label("Sensor Fault Flags")
+        .description("Any fault flags of the sensors")
+        .domainProperty(SO.Boolean)
+        .scope(PropertyScope.MEASUREMENT_PROPERTY)
+        .build())
+      .sample("sensor_fault_flags", true)
+      .build();
+  }
 }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/simulator/machine/MachineDataStreamAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/simulator/machine/MachineDataStreamAdapter.java
index e661a7c..aaf7a90 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/simulator/machine/MachineDataStreamAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/simulator/machine/MachineDataStreamAdapter.java
@@ -59,7 +59,7 @@
                 .withAssets(Assets.DOCUMENTATION, Assets.ICON)
                 .withLocales(Locales.EN)
                 .category(AdapterType.Debugging)
-                .requiredIntegerParameter(Labels.withId(WAIT_TIME_MS))
+                .requiredIntegerParameter(Labels.withId(WAIT_TIME_MS), 1000)
                 .requiredSingleValueSelection(Labels.withId(SELECTED_SIMULATOR_OPTION), Options.from(
                         "flowrate", "pressure", "waterlevel"))
                 .build();
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/set/FileProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/set/FileProtocol.java
index 25976de..8dcb342 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/set/FileProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/set/FileProtocol.java
@@ -121,11 +121,12 @@
             InputStream targetStream = FileProtocolUtils.getFileInputStream(this.selectedFilename);
             List<byte[]> dataByte = parser.parseNEvents(targetStream, 20);
 
-            EventSchema eventSchema = parser.getEventSchema(dataByte);
-
-            GuessSchema result = SchemaGuesser.guessSchma(eventSchema);
-
-            return result;
+            if (parser.supportsPreview()) {
+                return SchemaGuesser.guessSchema(parser.getSchemaAndSample(dataByte));
+            } else {
+                EventSchema eventSchema = parser.getEventSchema(dataByte);
+                return SchemaGuesser.guessSchema(eventSchema);
+            }
         } catch (FileNotFoundException e) {
             throw new ParseException("Could not read local file");
         }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/set/HttpProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/set/HttpProtocol.java
index 1feb4cc..eca0f25 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/set/HttpProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/set/HttpProtocol.java
@@ -116,7 +116,7 @@
 
         EventSchema eventSchema= parser.getEventSchema(dataByte);
 
-        GuessSchema result = SchemaGuesser.guessSchma(eventSchema);
+        GuessSchema result = SchemaGuesser.guessSchema(eventSchema);
 
         return result;
     }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/BrokerProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/BrokerProtocol.java
index 835fffc..e34d7f9 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/BrokerProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/BrokerProtocol.java
@@ -23,7 +23,6 @@
 import org.apache.streampipes.connect.api.IParser;
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
-import org.apache.streampipes.model.schema.EventSchema;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -48,9 +47,12 @@
   public GuessSchema getGuessSchema() throws ParseException {
 
     List<byte[]> eventByte = getNByteElements(1);
-    EventSchema eventSchema = parser.getEventSchema(eventByte);
 
-    return SchemaGuesser.guessSchma(eventSchema);
+    if (parser.supportsPreview()) {
+      return SchemaGuesser.guessSchema(parser.getSchemaAndSample(eventByte));
+    } else {
+      return SchemaGuesser.guessSchema(parser.getEventSchema(eventByte));
+    }
   }
 
   @Override
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileStreamProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileStreamProtocol.java
index 4b9368b..f88f5c5 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileStreamProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileStreamProtocol.java
@@ -211,11 +211,12 @@
 
     List<byte[]> dataByte = parser.parseNEvents(dataInputStream, 2);
 
-    EventSchema eventSchema = parser.getEventSchema(dataByte);
-
-    GuessSchema result = SchemaGuesser.guessSchma(eventSchema);
-
-    return result;
+    if (parser.supportsPreview()) {
+      return SchemaGuesser.guessSchema(parser.getSchemaAndSample(dataByte));
+    } else {
+      EventSchema eventSchema = parser.getEventSchema(dataByte);
+      return SchemaGuesser.guessSchema(eventSchema);
+    }
   }
 
   @Override
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpStreamProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpStreamProtocol.java
index 39a5dad..be68829 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpStreamProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpStreamProtocol.java
@@ -112,7 +112,7 @@
             dataByte.addAll(dataByte);
         }
         EventSchema eventSchema= parser.getEventSchema(dataByte);
-        GuessSchema result = SchemaGuesser.guessSchma(eventSchema);
+        GuessSchema result = SchemaGuesser.guessSchema(eventSchema);
 
         return result;
     }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/KafkaProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/KafkaProtocol.java
index 502aa7c..cdc8cb4 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/KafkaProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/KafkaProtocol.java
@@ -20,9 +20,11 @@
 
 import org.apache.commons.io.IOUtils;
 import org.apache.kafka.clients.consumer.*;
+import org.apache.kafka.common.KafkaException;
 import org.apache.kafka.common.TopicPartition;
 import org.apache.kafka.common.serialization.ByteArrayDeserializer;
 import org.apache.streampipes.commons.constants.GlobalStreamPipesConstants;
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.connect.SendToPipeline;
 import org.apache.streampipes.connect.adapter.model.generic.Protocol;
@@ -30,7 +32,7 @@
 import org.apache.streampipes.connect.api.IFormat;
 import org.apache.streampipes.connect.api.IParser;
 import org.apache.streampipes.connect.api.exception.ParseException;
-import org.apache.streampipes.container.api.ResolvesContainerProvidedOptions;
+import org.apache.streampipes.container.api.SupportsRuntimeConfig;
 import org.apache.streampipes.messaging.InternalEventProcessor;
 import org.apache.streampipes.messaging.kafka.SpKafkaConsumer;
 import org.apache.streampipes.model.AdapterType;
@@ -38,6 +40,8 @@
 import org.apache.streampipes.model.grounding.KafkaTransportProtocol;
 import org.apache.streampipes.model.grounding.SimpleTopicDefinition;
 import org.apache.streampipes.model.staticproperty.Option;
+import org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty;
+import org.apache.streampipes.model.staticproperty.StaticProperty;
 import org.apache.streampipes.pe.shared.config.kafka.KafkaConfig;
 import org.apache.streampipes.pe.shared.config.kafka.KafkaConnectUtils;
 import org.apache.streampipes.sdk.builder.adapter.ProtocolDescriptionBuilder;
@@ -45,7 +49,6 @@
 import org.apache.streampipes.sdk.helpers.AdapterSourceType;
 import org.apache.streampipes.sdk.helpers.Labels;
 import org.apache.streampipes.sdk.helpers.Locales;
-import org.apache.streampipes.sdk.helpers.Options;
 import org.apache.streampipes.sdk.utils.Assets;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,7 +58,7 @@
 import java.util.*;
 import java.util.stream.Collectors;
 
-public class KafkaProtocol extends BrokerProtocol implements ResolvesContainerProvidedOptions {
+public class KafkaProtocol extends BrokerProtocol implements SupportsRuntimeConfig {
 
     Logger logger = LoggerFactory.getLogger(KafkaProtocol.class);
     KafkaConfig config;
@@ -154,7 +157,7 @@
         return resultEventsByte;
     }
 
-    private Consumer<byte[], byte[]> createConsumer(KafkaConfig kafkaConfig) {
+    private Consumer<byte[], byte[]> createConsumer(KafkaConfig kafkaConfig) throws KafkaException {
         final Properties props = new Properties();
 
         kafkaConfig.getSecurityConfig().appendConfig(props);
@@ -165,6 +168,8 @@
         props.put(ConsumerConfig.GROUP_ID_CONFIG,
                 "KafkaExampleConsumer" + System.currentTimeMillis());
 
+        props.put(ConsumerConfig.DEFAULT_API_TIMEOUT_MS_CONFIG, 6000);
+
         props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
                 ByteArrayDeserializer.class.getName());
         props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
@@ -214,22 +219,30 @@
     }
 
     @Override
-    public List<Option> resolveOptions(String requestId, StaticPropertyExtractor extractor) {
+    public StaticProperty resolveConfiguration(String staticPropertyInternalName, StaticPropertyExtractor extractor) throws SpConfigurationException {
+        RuntimeResolvableOneOfStaticProperty config = extractor
+          .getStaticPropertyByName(KafkaConnectUtils.TOPIC_KEY, RuntimeResolvableOneOfStaticProperty.class);
         KafkaConfig kafkaConfig = KafkaConnectUtils.getConfig(extractor, false);
         boolean hideInternalTopics = extractor.slideToggleValue(KafkaConnectUtils.getHideInternalTopicsKey());
 
-        Consumer<byte[], byte[]> consumer = createConsumer(kafkaConfig);
+        try {
+            Consumer<byte[], byte[]> consumer = createConsumer(kafkaConfig);
+            Set<String> topics = consumer.listTopics().keySet();
+            consumer.close();
 
-        Set<String> topics = consumer.listTopics().keySet();
-        consumer.close();
+            if (hideInternalTopics) {
+                topics = topics
+                  .stream()
+                  .filter(t -> !t.startsWith(GlobalStreamPipesConstants.INTERNAL_TOPIC_PREFIX))
+                  .collect(Collectors.toSet());
+            }
 
-        if (hideInternalTopics) {
-            topics = topics
-                    .stream()
-                    .filter(t -> !t.startsWith(GlobalStreamPipesConstants.INTERNAL_TOPIC_PREFIX))
-                    .collect(Collectors.toSet());
+            config.setOptions(topics.stream().map(Option::new).collect(Collectors.toList()));
+
+            return config;
+        } catch (KafkaException e) {
+            throw new SpConfigurationException(e.getMessage(), e);
         }
-        return topics.stream().map(Option::new).collect(Collectors.toList());
     }
 
 
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/pulsar/PulsarProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/pulsar/PulsarProtocol.java
index 197456a..4f431c5 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/pulsar/PulsarProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/pulsar/PulsarProtocol.java
@@ -17,8 +17,10 @@
  */
 package org.apache.streampipes.connect.iiot.protocol.stream.pulsar;
 
+import java.io.IOException;
 import org.apache.pulsar.client.api.PulsarClient;
 import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.pulsar.client.api.Reader;
 import org.apache.streampipes.connect.SendToPipeline;
 import org.apache.streampipes.connect.adapter.model.generic.Protocol;
 import org.apache.streampipes.connect.adapter.sdk.ParameterExtractor;
@@ -68,18 +70,17 @@
   @Override
   protected List<byte[]> getNByteElements(int n) throws ParseException {
     List<byte[]> elements = new ArrayList<>();
-    InternalEventProcessor<byte[]> eventProcessor = elements::add;
-    PulsarConsumer consumer = new PulsarConsumer(this.brokerUrl, this.topic, eventProcessor, n);
-
-    Thread thread = new Thread(consumer);
-    thread.start();
-
-    while (consumer.getMessageCount() < n) {
-      try {
-        Thread.sleep(100);
-      } catch (InterruptedException e) {
-        e.printStackTrace();
+    try (PulsarClient pulsarClient = PulsarUtils.makePulsarClient(brokerUrl);
+         Reader<byte[]> reader = pulsarClient.newReader()
+                 .topic(topic)
+                 .create()) {
+      for (int i = 0; i < n; i++) {
+        if (reader.hasMessageAvailable()) {
+          elements.add(reader.readNext().getValue());
+        }
       }
+    } catch (IOException e) {
+      throw new ParseException("Failed to fetch messages.", e);
     }
     return elements;
   }
diff --git a/streampipes-extensions/streampipes-connect-adapters/pom.xml b/streampipes-extensions/streampipes-connect-adapters/pom.xml
index 713a33c..40c2f3f 100644
--- a/streampipes-extensions/streampipes-connect-adapters/pom.xml
+++ b/streampipes-extensions/streampipes-connect-adapters/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-extensions</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>streampipes-connect-adapters</artifactId>
@@ -37,7 +37,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect-container-worker</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.graalvm.nativeimage</groupId>
@@ -48,12 +48,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-elements-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container-extensions</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -215,5 +215,4 @@
         </plugins>
         <finalName>streampipes-connect-adapters</finalName>
     </build>
-
 </project>
diff --git a/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/ConnectAdapterInit.java b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/ConnectAdapterInit.java
index 78423b8..624b9e2 100644
--- a/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/ConnectAdapterInit.java
+++ b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/ConnectAdapterInit.java
@@ -26,6 +26,8 @@
 import org.apache.streampipes.connect.adapters.image.set.ImageSetAdapter;
 import org.apache.streampipes.connect.adapters.image.stream.ImageStreamAdapter;
 import org.apache.streampipes.connect.adapters.iss.IssAdapter;
+import org.apache.streampipes.connect.adapters.netio.NetioMQTTAdapter;
+import org.apache.streampipes.connect.adapters.netio.NetioRestAdapter;
 import org.apache.streampipes.connect.adapters.simulator.random.RandomDataSetAdapter;
 import org.apache.streampipes.connect.adapters.simulator.random.RandomDataStreamAdapter;
 import org.apache.streampipes.connect.adapters.slack.SlackAdapter;
@@ -45,23 +47,25 @@
   @Override
   public SpServiceDefinition provideServiceDefinition() {
     return SpServiceDefinitionBuilder.create("connect-adapter",
-            "StreamPipes Connect Worker Main",
-            "",8001)
-            .registerAdapter(new GdeltAdapter())
-            .registerAdapter(new CoindeskBitcoinAdapter())
-            .registerAdapter(new IexCloudNewsAdapter())
-            .registerAdapter(new IexCloudStockAdapter())
-            .registerAdapter(new RandomDataSetAdapter())
-            .registerAdapter(new RandomDataStreamAdapter())
-            .registerAdapter(new SlackAdapter())
-            .registerAdapter(new WikipediaEditedArticlesAdapter())
-            .registerAdapter(new WikipediaNewArticlesAdapter())
-            .registerAdapter(new ImageStreamAdapter())
-            .registerAdapter(new ImageSetAdapter())
-            .registerAdapter(new IssAdapter())
-            .registerAdapter(new FlicMQTTAdapter())
-            .registerAdapter(new TISensorTag())
-            .build();
+        "StreamPipes Connect Worker Main",
+        "", 8001)
+      .registerAdapter(new GdeltAdapter())
+      .registerAdapter(new CoindeskBitcoinAdapter())
+      .registerAdapter(new NetioRestAdapter())
+      .registerAdapter(new NetioMQTTAdapter())
+      .registerAdapter(new IexCloudNewsAdapter())
+      .registerAdapter(new IexCloudStockAdapter())
+      .registerAdapter(new RandomDataSetAdapter())
+      .registerAdapter(new RandomDataStreamAdapter())
+      .registerAdapter(new SlackAdapter())
+      .registerAdapter(new WikipediaEditedArticlesAdapter())
+      .registerAdapter(new WikipediaNewArticlesAdapter())
+      .registerAdapter(new ImageStreamAdapter())
+      .registerAdapter(new ImageSetAdapter())
+      .registerAdapter(new IssAdapter())
+      .registerAdapter(new FlicMQTTAdapter())
+      .registerAdapter(new TISensorTag())
+      .build();
   }
 
 }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioMQTTAdapter.java b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioMQTTAdapter.java
similarity index 95%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioMQTTAdapter.java
rename to streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioMQTTAdapter.java
index d692cd7..f2686c8 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioMQTTAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioMQTTAdapter.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.connect.iiot.adapters.netio;
+package org.apache.streampipes.connect.adapters.netio;
 
 import com.google.gson.Gson;
 
@@ -24,8 +24,8 @@
 import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.adapter.model.pipeline.AdapterPipeline;
 import org.apache.streampipes.connect.adapter.model.specific.SpecificDataStreamAdapter;
-import org.apache.streampipes.connect.iiot.adapters.netio.model.NetioAllPowerOutputs;
-import org.apache.streampipes.connect.iiot.adapters.netio.model.NetioPowerOutput;
+import org.apache.streampipes.connect.adapters.netio.model.NetioAllPowerOutputs;
+import org.apache.streampipes.connect.adapters.netio.model.NetioPowerOutput;
 import org.apache.streampipes.pe.shared.config.mqtt.*;
 import org.apache.streampipes.messaging.InternalEventProcessor;
 import org.apache.streampipes.model.AdapterType;
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioRestAdapter.java b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioRestAdapter.java
similarity index 95%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioRestAdapter.java
rename to streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioRestAdapter.java
index 7d7a5d3..4b4c9f4 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioRestAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioRestAdapter.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.connect.iiot.adapters.netio;
+package org.apache.streampipes.connect.adapters.netio;
 
 import com.google.gson.Gson;
 import org.apache.http.HttpHost;
@@ -24,12 +24,12 @@
 import org.apache.http.client.fluent.Executor;
 import org.apache.http.client.fluent.Request;
 import org.apache.streampipes.connect.adapter.Adapter;
-import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.adapter.sdk.ParameterExtractor;
 import org.apache.streampipes.connect.adapter.util.PollingSettings;
-import org.apache.streampipes.connect.iiot.adapters.PullAdapter;
-import org.apache.streampipes.connect.iiot.adapters.netio.model.NetioAllPowerOutputs;
-import org.apache.streampipes.connect.iiot.adapters.netio.model.NetioPowerOutput;
+import org.apache.streampipes.connect.adapters.PullAdapter;
+import org.apache.streampipes.connect.adapters.netio.model.NetioAllPowerOutputs;
+import org.apache.streampipes.connect.adapters.netio.model.NetioPowerOutput;
+import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.model.AdapterType;
 import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioUtils.java b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioUtils.java
similarity index 96%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioUtils.java
rename to streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioUtils.java
index b7da893..2a47cc1 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/NetioUtils.java
+++ b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/NetioUtils.java
@@ -16,10 +16,10 @@
  *
  */
 
-package org.apache.streampipes.connect.iiot.adapters.netio;
+package org.apache.streampipes.connect.adapters.netio;
 
-import org.apache.streampipes.connect.iiot.adapters.netio.model.NetioGlobalMeasure;
-import org.apache.streampipes.connect.iiot.adapters.netio.model.NetioPowerOutput;
+import org.apache.streampipes.connect.adapters.netio.model.NetioGlobalMeasure;
+import org.apache.streampipes.connect.adapters.netio.model.NetioPowerOutput;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventSchema;
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioAllPowerOutputs.java b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioAllPowerOutputs.java
similarity index 95%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioAllPowerOutputs.java
rename to streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioAllPowerOutputs.java
index c816ca4..1b4e5ac 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioAllPowerOutputs.java
+++ b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioAllPowerOutputs.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.connect.iiot.adapters.netio.model;
+package org.apache.streampipes.connect.adapters.netio.model;
 
 import com.google.gson.annotations.SerializedName;
 
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioGlobalMeasure.java b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioGlobalMeasure.java
similarity index 96%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioGlobalMeasure.java
rename to streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioGlobalMeasure.java
index 0a6c9a6..34c0d22 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioGlobalMeasure.java
+++ b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioGlobalMeasure.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.connect.iiot.adapters.netio.model;
+package org.apache.streampipes.connect.adapters.netio.model;
 
 
 import com.google.gson.annotations.SerializedName;
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioPowerOutput.java b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioPowerOutput.java
similarity index 97%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioPowerOutput.java
rename to streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioPowerOutput.java
index f2b75eb..2b2c6ae 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/netio/model/NetioPowerOutput.java
+++ b/streampipes-extensions/streampipes-connect-adapters/src/main/java/org/apache/streampipes/connect/adapters/netio/model/NetioPowerOutput.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.connect.iiot.adapters.netio.model;
+package org.apache.streampipes.connect.adapters.netio.model;
 
 import com.google.gson.annotations.SerializedName;
 
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/documentation.md b/streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/documentation.md
similarity index 100%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/documentation.md
rename to streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/documentation.md
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/icon.png b/streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/icon.png
similarity index 100%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/icon.png
rename to streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/icon.png
Binary files differ
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/strings.en b/streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/strings.en
similarity index 100%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/strings.en
rename to streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.mqtt/strings.en
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/documentation.md b/streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/documentation.md
similarity index 100%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/documentation.md
rename to streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/documentation.md
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/icon.png b/streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/icon.png
similarity index 100%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/icon.png
rename to streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/icon.png
Binary files differ
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/strings.en b/streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/strings.en
similarity index 100%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/strings.en
rename to streampipes-extensions/streampipes-connect-adapters/src/main/resources/org.apache.streampipes.connect.iiot.adapters.netio.rest/strings.en
diff --git a/streampipes-extensions/streampipes-processors-image-processing-jvm/Dockerfile b/streampipes-extensions/streampipes-extensions-all-iiot/Dockerfile
similarity index 73%
rename from streampipes-extensions/streampipes-processors-image-processing-jvm/Dockerfile
rename to streampipes-extensions/streampipes-extensions-all-iiot/Dockerfile
index e64e6d1..99ba527 100644
--- a/streampipes-extensions/streampipes-processors-image-processing-jvm/Dockerfile
+++ b/streampipes-extensions/streampipes-extensions-all-iiot/Dockerfile
@@ -13,16 +13,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
+FROM eclipse-temurin:11-jre-focal
 
 ENV CONSUL_LOCATION consul
 
 EXPOSE 8090
-# needed pkgs processors-image-processing-jvm
-RUN apk --update add --no-cache \
-    fontconfig \
-    ttf-dejavu
 
-COPY target/streampipes-processors-image-processing-jvm.jar  /streampipes-processing-element-container.jar
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
+# needed pkgs processors-image-processing-jvm
+RUN apt-get update && apt-get install ttf-dejavu-core && apt-get install fontconfig
+
+COPY target/streampipes-extensions-all-iiot.jar  /streampipes-extensions-all-iiot.jar
+
+ENTRYPOINT ["java", "-jar", "/streampipes-extensions-all-iiot.jar"]
diff --git a/streampipes-extensions/streampipes-extensions-all-iiot/pom.xml b/streampipes-extensions/streampipes-extensions-all-iiot/pom.xml
new file mode 100644
index 0000000..74511fa
--- /dev/null
+++ b/streampipes-extensions/streampipes-extensions-all-iiot/pom.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>streampipes-extensions</artifactId>
+        <groupId>org.apache.streampipes</groupId>
+        <version>0.71.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>streampipes-extensions-all-iiot</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-container-extensions</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.graalvm.nativeimage</groupId>
+                    <artifactId>svm</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-processors-filters-jvm</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.graalvm.nativeimage</groupId>
+                    <artifactId>svm</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-processors-filters-siddhi</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-processors-transformation-jvm</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-sinks-brokers-jvm</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-sinks-databases-jvm</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-sinks-internal-jvm</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-sinks-notifications-jvm</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-processors-enricher-jvm</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-processors-change-detection-jvm</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+
+        <!-- 3rd party dependencies to avoid convergence errors -->
+        <dependency>
+            <groupId>io.dropwizard.metrics</groupId>
+            <artifactId>metrics-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-handler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.atteo.classindex</groupId>
+            <artifactId>classindex</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-connect-adapters-iiot</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
+            <classifier>embed</classifier>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                        <configuration>
+                            <mainClass>org.apache.streampipes.extensions.all.iiot.AllExtensionsIIoTInit</mainClass>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <finalName>streampipes-extensions-all-iiot</finalName>
+    </build>
+</project>
diff --git a/streampipes-extensions/streampipes-extensions-all-iiot/src/main/java/org/apache/streampipes/extensions/all/iiot/AllExtensionsIIoTInit.java b/streampipes-extensions/streampipes-extensions-all-iiot/src/main/java/org/apache/streampipes/extensions/all/iiot/AllExtensionsIIoTInit.java
new file mode 100644
index 0000000..d58da6e
--- /dev/null
+++ b/streampipes-extensions/streampipes-extensions-all-iiot/src/main/java/org/apache/streampipes/extensions/all/iiot/AllExtensionsIIoTInit.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.extensions.all.iiot;
+
+import org.apache.streampipes.connect.iiot.ConnectAdapterIiotInit;
+import org.apache.streampipes.container.extensions.ExtensionsModelSubmitter;
+import org.apache.streampipes.container.model.SpServiceDefinition;
+import org.apache.streampipes.container.model.SpServiceDefinitionBuilder;
+import org.apache.streampipes.dataformat.cbor.CborDataFormatFactory;
+import org.apache.streampipes.dataformat.fst.FstDataFormatFactory;
+import org.apache.streampipes.dataformat.json.JsonDataFormatFactory;
+import org.apache.streampipes.dataformat.smile.SmileDataFormatFactory;
+import org.apache.streampipes.messaging.jms.SpJmsProtocolFactory;
+import org.apache.streampipes.messaging.kafka.SpKafkaProtocolFactory;
+import org.apache.streampipes.messaging.mqtt.SpMqttProtocolFactory;
+import org.apache.streampipes.processors.changedetection.jvm.ChangeDetectionJvmInit;
+import org.apache.streampipes.processors.enricher.jvm.EnricherJvmInit;
+import org.apache.streampipes.processors.filters.jvm.FiltersJvmInit;
+import org.apache.streampipes.processors.siddhi.FiltersSiddhiInit;
+import org.apache.streampipes.processors.transformation.jvm.TransformationJvmInit;
+import org.apache.streampipes.sinks.brokers.jvm.BrokersJvmInit;
+import org.apache.streampipes.sinks.databases.jvm.DatabasesJvmInit;
+import org.apache.streampipes.sinks.internal.jvm.SinksInternalJvmInit;
+import org.apache.streampipes.sinks.notifications.jvm.SinksNotificationsJvmInit;
+
+public class AllExtensionsIIoTInit extends ExtensionsModelSubmitter {
+
+  public static void main (String[] args) {
+    new AllExtensionsIIoTInit().init();
+  }
+
+  @Override
+  public SpServiceDefinition provideServiceDefinition() {
+    return SpServiceDefinitionBuilder.create("org.apache.streampipes.extensions.all.iiot",
+        "StreamPipes Extensions (IIoT only)",
+        "", 8090)
+      .merge(new ConnectAdapterIiotInit().provideServiceDefinition())
+      .merge(new SinksInternalJvmInit().provideServiceDefinition())
+      .merge(new FiltersJvmInit().provideServiceDefinition())
+      .merge(new ChangeDetectionJvmInit().provideServiceDefinition())
+      .merge(new EnricherJvmInit().provideServiceDefinition())
+      .merge(new FiltersSiddhiInit().provideServiceDefinition())
+      .merge(new TransformationJvmInit().provideServiceDefinition())
+      .merge(new BrokersJvmInit().provideServiceDefinition())
+      .merge(new DatabasesJvmInit().provideServiceDefinition())
+      .merge(new SinksNotificationsJvmInit().provideServiceDefinition())
+      .registerMessagingFormats(
+        new JsonDataFormatFactory(),
+        new CborDataFormatFactory(),
+        new SmileDataFormatFactory(),
+        new FstDataFormatFactory())
+      .registerMessagingProtocols(
+        new SpKafkaProtocolFactory(),
+        new SpJmsProtocolFactory(),
+        new SpMqttProtocolFactory())
+      .build();
+  }
+}
diff --git a/streampipes-extensions/streampipes-extensions-all-jvm/pom.xml b/streampipes-extensions/streampipes-extensions-all-jvm/pom.xml
index 68151b8..a904a84 100644
--- a/streampipes-extensions/streampipes-extensions-all-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-extensions-all-jvm/pom.xml
@@ -20,7 +20,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -34,7 +34,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container-extensions</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.graalvm.nativeimage</groupId>
@@ -46,7 +46,7 @@
             <dependency>
                 <groupId>org.apache.streampipes</groupId>
                 <artifactId>streampipes-pipeline-elements-all-jvm</artifactId>
-                <version>0.70.0-SNAPSHOT</version>
+                <version>0.71.0-SNAPSHOT</version>
                 <classifier>embed</classifier>
             </dependency>
 
@@ -54,13 +54,13 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect-adapters</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <classifier>embed</classifier>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect-adapters-iiot</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <classifier>embed</classifier>
         </dependency>
 
@@ -90,5 +90,4 @@
         </plugins>
         <finalName>streampipes-extensions-all-jvm</finalName>
     </build>
-
 </project>
diff --git a/streampipes-extensions/streampipes-pipeline-elements-all-flink/pom.xml b/streampipes-extensions/streampipes-pipeline-elements-all-flink/pom.xml
index b722ff1..e2a091f 100644
--- a/streampipes-extensions/streampipes-pipeline-elements-all-flink/pom.xml
+++ b/streampipes-extensions/streampipes-pipeline-elements-all-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -35,43 +35,43 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-aggregation-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <classifier>embed</classifier>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-enricher-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-geo-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-pattern-detection-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-statistics-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-text-mining-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-transformation-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sinks-databases-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- 3rd party dependencies to avoid convergence errors -->
diff --git a/streampipes-extensions/streampipes-pipeline-elements-all-jvm/pom.xml b/streampipes-extensions/streampipes-pipeline-elements-all-jvm/pom.xml
index 9feec84..133905e 100644
--- a/streampipes-extensions/streampipes-pipeline-elements-all-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-pipeline-elements-all-jvm/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -35,8 +35,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-filters-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.graalvm.nativeimage</groupId>
@@ -47,68 +46,57 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-image-processing-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-filters-siddhi</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-text-mining-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-transformation-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sinks-brokers-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sinks-databases-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sinks-internal-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sinks-notifications-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-enricher-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-geo-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-processors-change-detection-jvm</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
-            <classifier>embed</classifier>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- 3rd party dependencies to avoid convergence errors -->
diff --git a/streampipes-extensions/streampipes-pipeline-elements-data-simulator/pom.xml b/streampipes-extensions/streampipes-pipeline-elements-data-simulator/pom.xml
index cb40a4a..7bb7d9a 100644
--- a/streampipes-extensions/streampipes-pipeline-elements-data-simulator/pom.xml
+++ b/streampipes-extensions/streampipes-pipeline-elements-data-simulator/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -75,5 +75,4 @@
             </exclusions>
         </dependency>
     </dependencies>
-
 </project>
diff --git a/streampipes-extensions/streampipes-pipeline-elements-shared/pom.xml b/streampipes-extensions/streampipes-pipeline-elements-shared/pom.xml
index a5cead8..643d091 100644
--- a/streampipes-extensions/streampipes-pipeline-elements-shared/pom.xml
+++ b/streampipes-extensions/streampipes-pipeline-elements-shared/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -39,12 +39,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
@@ -54,12 +54,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-kafka</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/streampipes-extensions/streampipes-processors-aggregation-flink/Dockerfile b/streampipes-extensions/streampipes-processors-aggregation-flink/Dockerfile
deleted file mode 100644
index 695eae0..0000000
--- a/streampipes-extensions/streampipes-processors-aggregation-flink/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-aggregation-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-aggregation-flink/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-aggregation-flink/aarch64.Dockerfile
deleted file mode 100644
index 2e3fc3c..0000000
--- a/streampipes-extensions/streampipes-processors-aggregation-flink/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-aggregation-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-aggregation-flink/arm.Dockerfile b/streampipes-extensions/streampipes-processors-aggregation-flink/arm.Dockerfile
deleted file mode 100644
index 7fe7fb9..0000000
--- a/streampipes-extensions/streampipes-processors-aggregation-flink/arm.Dockerfile
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-aggregation-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-aggregation-flink/development/env b/streampipes-extensions/streampipes-processors-aggregation-flink/development/env
deleted file mode 100644
index 5b3c9da..0000000
--- a/streampipes-extensions/streampipes-processors-aggregation-flink/development/env
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6005
-SP_HOST=host.docker.internal
-SP_DEBUG=true
-SP_FLINK_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-aggregation-flink/pom.xml b/streampipes-extensions/streampipes-processors-aggregation-flink/pom.xml
index f1ff41f..d0fe1ac 100644
--- a/streampipes-extensions/streampipes-processors-aggregation-flink/pom.xml
+++ b/streampipes-extensions/streampipes-processors-aggregation-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -36,12 +36,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -112,7 +112,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-test-utils</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/streampipes-extensions/streampipes-processors-change-detection-jvm/development/env b/streampipes-extensions/streampipes-processors-change-detection-jvm/development/env
deleted file mode 100644
index 2e01490..0000000
--- a/streampipes-extensions/streampipes-processors-change-detection-jvm/development/env
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6018
-SP_HOST=localhost
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-change-detection-jvm/pom.xml b/streampipes-extensions/streampipes-processors-change-detection-jvm/pom.xml
index 88b4c64..725fcef 100644
--- a/streampipes-extensions/streampipes-processors-change-detection-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-change-detection-jvm/pom.xml
@@ -21,60 +21,23 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-processors-change-detection-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-processors-change-detection-jvm</finalName>
-    </build>
-
 </project>
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/Dockerfile b/streampipes-extensions/streampipes-processors-enricher-flink/Dockerfile
deleted file mode 100644
index b0c8a48..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-enricher-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-enricher-flink/aarch64.Dockerfile
deleted file mode 100644
index 938661d..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-enricher-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/arm.Dockerfile b/streampipes-extensions/streampipes-processors-enricher-flink/arm.Dockerfile
deleted file mode 100644
index 4d26bd7..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-enricher-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/development/env b/streampipes-extensions/streampipes-processors-enricher-flink/development/env
deleted file mode 100644
index e33bec4..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/development/env
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6010
-SP_HOST=host.docker.internal
-SP_DEBUG=true
-SP_FLINK_DEBUG=true
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/pom.xml b/streampipes-extensions/streampipes-processors-enricher-flink/pom.xml
index dfc7b03..7ffcf7e 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/pom.xml
+++ b/streampipes-extensions/streampipes-processors-enricher-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -37,12 +37,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/EnricherFlinkInit.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/EnricherFlinkInit.java
index 2d36358a..28d7803 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/EnricherFlinkInit.java
+++ b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/EnricherFlinkInit.java
@@ -29,10 +29,7 @@
 import org.apache.streampipes.messaging.kafka.SpKafkaProtocolFactory;
 import org.apache.streampipes.messaging.mqtt.SpMqttProtocolFactory;
 import org.apache.streampipes.processors.enricher.flink.config.ConfigKeys;
-import org.apache.streampipes.processors.enricher.flink.processor.math.mathop.MathOpController;
-import org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop.StaticMathOpController;
 import org.apache.streampipes.processors.enricher.flink.processor.timestamp.TimestampController;
-import org.apache.streampipes.processors.enricher.flink.processor.trigonometry.TrigonometryController;
 import org.apache.streampipes.processors.enricher.flink.processor.urldereferencing.UrlDereferencingController;
 
 public class EnricherFlinkInit extends StandaloneModelSubmitter {
@@ -48,10 +45,7 @@
                     "",
                     8090)
             .registerPipelineElements(new TimestampController(),
-                    new MathOpController(),
-                    new StaticMathOpController(),
-                    new UrlDereferencingController(),
-                    new TrigonometryController())
+                    new UrlDereferencingController())
             .registerMessagingFormats(
                     new JsonDataFormatFactory(),
                     new CborDataFormatFactory(),
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOp.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOp.java
deleted file mode 100644
index 13ce569..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOp.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.math.mathop;
-
-import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.util.Collector;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.processors.enricher.flink.processor.math.operation.Operation;
-
-public class MathOp implements FlatMapFunction<Event, Event> {
-
-    private Operation operation;
-    private String leftOperand;
-    private String rightOperand;
-    private String resulField;
-
-    public MathOp(Operation operation, String leftOperand, String rightOperand, String resulField) {
-        this.operation = operation;
-        this.leftOperand = leftOperand;
-        this.rightOperand = rightOperand;
-        this.resulField = resulField;
-    }
-
-    @Override
-    public void flatMap(Event in, Collector<Event> out) throws Exception {
-        Double leftValue  = in.getFieldBySelector(leftOperand).getAsPrimitive().getAsDouble();
-        Double rightValue = in.getFieldBySelector(rightOperand).getAsPrimitive().getAsDouble();
-
-        Double result = operation.operate(leftValue, rightValue);
-        in.addField(resulField, result);
-
-        out.collect(in);
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpController.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpController.java
deleted file mode 100644
index f5c4f2e..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpController.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.math.mathop;
-
-import org.apache.streampipes.client.StreamPipesClient;
-import org.apache.streampipes.container.config.ConfigExtractor;
-import org.apache.streampipes.model.DataProcessorType;
-import org.apache.streampipes.model.graph.DataProcessorDescription;
-import org.apache.streampipes.model.graph.DataProcessorInvocation;
-import org.apache.streampipes.model.schema.PropertyScope;
-import org.apache.streampipes.processors.enricher.flink.processor.math.operation.*;
-import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
-import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
-import org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor;
-import org.apache.streampipes.sdk.helpers.*;
-import org.apache.streampipes.sdk.utils.Assets;
-import org.apache.streampipes.vocabulary.SO;
-import org.apache.streampipes.wrapper.flink.FlinkDataProcessorDeclarer;
-import org.apache.streampipes.wrapper.flink.FlinkDataProcessorRuntime;
-
-public class MathOpController extends FlinkDataProcessorDeclarer<MathOpParameters> {
-
-  private final String RESULT_FIELD = "calculationResult";
-  private final String LEFT_OPERAND = "leftOperand";
-  private final String RIGHT_OPERAND = "rightOperand";
-  private final String OPERATION = "operation";
-
-  @Override
-  public DataProcessorDescription declareModel() {
-    return ProcessingElementBuilder.create("org.apache.streampipes.processors.enricher.flink.processor.math.mathop")
-            .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-            .withLocales(Locales.EN)
-            .category(DataProcessorType.ALGORITHM)
-            .requiredStream(StreamRequirementsBuilder
-                    .create()
-                    .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),
-                            Labels.withId(LEFT_OPERAND),
-                            PropertyScope.NONE)
-                    .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),
-                            Labels.withId(RIGHT_OPERAND),
-                            PropertyScope.NONE)
-                    .build())
-            .outputStrategy(
-                    OutputStrategies.append(
-                            EpProperties.numberEp(Labels.empty(), RESULT_FIELD, SO.Number)))
-            .requiredSingleValueSelection(Labels.withId(OPERATION), Options.from("+", "-", "/",
-                    "*", "%"))
-            .build();
-  }
-
-  @Override
-  public FlinkDataProcessorRuntime<MathOpParameters> getRuntime(DataProcessorInvocation graph,
-                                                                ProcessingElementParameterExtractor extractor,
-                                                                ConfigExtractor configExtractor,
-                                                                StreamPipesClient streamPipesClient) {
-    String leftOperand = extractor.mappingPropertyValue(LEFT_OPERAND);
-    String rightOperand = extractor.mappingPropertyValue(RIGHT_OPERAND);
-    String operation = extractor.selectedSingleValue(OPERATION, String.class);
-
-    Operation arithmeticOperation = null;
-    switch (operation) {
-      case "+":
-        arithmeticOperation = new OperationAddition();
-        break;
-      case "-":
-        arithmeticOperation = new OperationSubtracting();
-        break;
-      case "*":
-        arithmeticOperation = new OperationMultiply();
-        break;
-      case "/":
-        arithmeticOperation = new OperationDivide();
-        break;
-      case "%":
-        arithmeticOperation = new OperationModulo();
-    }
-
-    MathOpParameters parameters = new MathOpParameters(graph, arithmeticOperation, leftOperand, rightOperand, RESULT_FIELD);
-
-    return new MathOpProgram(parameters, configExtractor, streamPipesClient);
-  }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpParameters.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpParameters.java
deleted file mode 100644
index 228a0ed..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpParameters.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.math.mathop;
-
-import org.apache.streampipes.model.graph.DataProcessorInvocation;
-import org.apache.streampipes.processors.enricher.flink.processor.math.operation.Operation;
-import org.apache.streampipes.wrapper.params.binding.EventProcessorBindingParams;
-
-public class MathOpParameters extends EventProcessorBindingParams {
-
-    private Operation operation;
-    private String leftOperand;
-    private String rightOperand;
-    private String resultField;
-
-    public MathOpParameters(DataProcessorInvocation graph, Operation operation, String leftOperand, String rightOperand, String resultField) {
-        super(graph);
-        this.operation = operation;
-        this.leftOperand = leftOperand;
-        this.rightOperand = rightOperand;
-        this.resultField = resultField;
-    }
-
-    public Operation getOperation() {
-        return operation;
-    }
-
-    public String getLeftOperand() {
-        return leftOperand;
-    }
-
-    public String getRightOperand() {
-        return rightOperand;
-    }
-
-    public String getResultField() {
-        return resultField;
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpProgram.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpProgram.java
deleted file mode 100644
index bb61a3e..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/mathop/MathOpProgram.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.math.mathop;
-
-import org.apache.flink.streaming.api.datastream.DataStream;
-import org.apache.streampipes.client.StreamPipesClient;
-import org.apache.streampipes.container.config.ConfigExtractor;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.processors.enricher.flink.AbstractEnricherProgram;
-
-public class MathOpProgram extends AbstractEnricherProgram<MathOpParameters> {
-
-    public MathOpProgram(MathOpParameters params,
-                         ConfigExtractor configExtractor,
-                         StreamPipesClient streamPipesClient) {
-        super(params, configExtractor, streamPipesClient);
-    }
-
-    @Override
-    protected DataStream<Event> getApplicationLogic(DataStream<Event>... dataStreams) {
-        return dataStreams[0]
-                .flatMap(new MathOp(params.getOperation(), params.getLeftOperand(),
-                                    params.getRightOperand(), params.getResultField()));
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOp.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOp.java
deleted file mode 100644
index 60e68df..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOp.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop;
-
-import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.util.Collector;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.processors.enricher.flink.processor.math.operation.Operation;
-
-public class StaticMathOp implements FlatMapFunction<Event, Event> {
-
-    private Operation operation;
-    private String leftOperand;
-    private double rightOperandValue;
-    private String resulField;
-
-    public StaticMathOp(Operation operation, String leftOperand, double rightOperandValue, String resultField) {
-        this.operation = operation;
-        this.leftOperand = leftOperand;
-        this.rightOperandValue = rightOperandValue;
-        this.resulField = resultField;
-    }
-
-    @Override
-    public void flatMap(Event in, Collector<Event> out) throws Exception {
-        Double leftValue  = Double.parseDouble(String.valueOf(in.getFieldBySelector(leftOperand)
-                .getAsPrimitive().getAsDouble()));
-
-        Double result = operation.operate(leftValue, rightOperandValue);
-        in.updateFieldBySelector(leftOperand, result);
-
-        out.collect(in);
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpController.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpController.java
deleted file mode 100644
index 6cf6bbd..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpController.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop;
-
-import org.apache.streampipes.client.StreamPipesClient;
-import org.apache.streampipes.container.config.ConfigExtractor;
-import org.apache.streampipes.model.DataProcessorType;
-import org.apache.streampipes.model.graph.DataProcessorDescription;
-import org.apache.streampipes.model.graph.DataProcessorInvocation;
-import org.apache.streampipes.model.schema.PropertyScope;
-import org.apache.streampipes.processors.enricher.flink.processor.math.operation.*;
-import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
-import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
-import org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor;
-import org.apache.streampipes.sdk.helpers.*;
-import org.apache.streampipes.sdk.utils.Assets;
-import org.apache.streampipes.wrapper.flink.FlinkDataProcessorDeclarer;
-import org.apache.streampipes.wrapper.flink.FlinkDataProcessorRuntime;
-
-public class StaticMathOpController extends FlinkDataProcessorDeclarer<StaticMathOpParameters> {
-
-  private final String RESULT_FIELD = "calculationResultStatic";
-  private final String LEFT_OPERAND = "leftOperand";
-  private final String RIGHT_OPERAND_VALUE = "rightOperandValue";
-  private final String OPERATION = "operation";
-
-  @Override
-  public DataProcessorDescription declareModel() {
-    return ProcessingElementBuilder.create("org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop")
-            .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-            .withLocales(Locales.EN)
-            .category(DataProcessorType.ALGORITHM)
-            .requiredStream(StreamRequirementsBuilder
-                    .create()
-                    .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),
-                            Labels.withId(LEFT_OPERAND),
-                            PropertyScope.NONE)
-                    .build())
-            .requiredFloatParameter(Labels.withId(RIGHT_OPERAND_VALUE))
-            .outputStrategy(
-                    OutputStrategies.keep())
-            .requiredSingleValueSelection(Labels.withId(OPERATION),
-                    Options.from("+", "-", "/", "*", "%"))
-            .build();
-  }
-
-  @Override
-  public FlinkDataProcessorRuntime<StaticMathOpParameters> getRuntime(DataProcessorInvocation graph,
-                                                                      ProcessingElementParameterExtractor extractor,
-                                                                      ConfigExtractor configExtractor,
-                                                                      StreamPipesClient streamPipesClient) {
-    String leftOperand = extractor.mappingPropertyValue(LEFT_OPERAND);
-    double rightOperand = extractor.singleValueParameter(RIGHT_OPERAND_VALUE, Double.class);
-    String operation = extractor.selectedSingleValue(OPERATION, String.class);
-
-    Operation arithmeticOperation = null;
-    switch (operation) {
-      case "+":
-        arithmeticOperation = new OperationAddition();
-        break;
-      case "-":
-        arithmeticOperation = new OperationSubtracting();
-        break;
-      case "*":
-        arithmeticOperation = new OperationMultiply();
-        break;
-      case "/":
-        arithmeticOperation = new OperationDivide();
-        break;
-      case "%":
-        arithmeticOperation = new OperationModulo();
-    }
-
-    StaticMathOpParameters parameters = new StaticMathOpParameters(graph, arithmeticOperation, leftOperand, rightOperand, RESULT_FIELD);
-
-    return new StaticMathOpProgram(parameters, configExtractor, streamPipesClient);
-
-  }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpParameters.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpParameters.java
deleted file mode 100644
index b8466d2..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpParameters.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop;
-
-import org.apache.streampipes.model.graph.DataProcessorInvocation;
-import org.apache.streampipes.processors.enricher.flink.processor.math.operation.Operation;
-import org.apache.streampipes.wrapper.params.binding.EventProcessorBindingParams;
-
-public class StaticMathOpParameters extends EventProcessorBindingParams {
-
-    private Operation operation;
-    private String leftOperand;
-    private double rightOperandValue;
-    private String resultField;
-
-    public StaticMathOpParameters(DataProcessorInvocation graph, Operation operation, String leftOperand, double rightOperandValue, String resultField) {
-        super(graph);
-        this.operation = operation;
-        this.leftOperand = leftOperand;
-        this.rightOperandValue = rightOperandValue;
-        this.resultField = resultField;
-    }
-
-    public Operation getOperation() {
-        return operation;
-    }
-
-    public String getLeftOperand() {
-        return leftOperand;
-    }
-
-    public double getRightOperandValue() {
-        return rightOperandValue;
-    }
-
-    public String getResultField() {
-        return resultField;
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpProgram.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpProgram.java
deleted file mode 100644
index 57c0dcf..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/staticmathop/StaticMathOpProgram.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop;
-
-import org.apache.flink.streaming.api.datastream.DataStream;
-import org.apache.streampipes.client.StreamPipesClient;
-import org.apache.streampipes.container.config.ConfigExtractor;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.processors.enricher.flink.AbstractEnricherProgram;
-
-public class StaticMathOpProgram extends AbstractEnricherProgram<StaticMathOpParameters> {
-
-    public StaticMathOpProgram(StaticMathOpParameters params,
-                               ConfigExtractor configExtractor,
-                               StreamPipesClient streamPipesClient) {
-        super(params, configExtractor, streamPipesClient);
-    }
-
-    @Override
-    protected DataStream<Event> getApplicationLogic(DataStream<Event>... dataStreams) {
-        return dataStreams[0]
-                .flatMap(new StaticMathOp(params.getOperation(), params.getLeftOperand(),
-                        params.getRightOperandValue(), params.getResultField()));
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/Trigonometry.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/Trigonometry.java
deleted file mode 100644
index e7fd00f..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/Trigonometry.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.trigonometry;
-
-import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.util.Collector;
-import org.apache.streampipes.model.runtime.Event;
-
-public class Trigonometry implements FlatMapFunction<Event, Event> {
-
-    private String operand;
-    private Operation operation;
-    private String resultField;
-
-    public Trigonometry(String operand, Operation operation, String resultField) {
-        this.operand = operand;
-        this.operation = operation;
-        this.resultField = resultField;
-    }
-
-    @Override
-    public void flatMap(Event in, Collector<Event> out) throws Exception {
-        double value = in.getFieldBySelector(operand).getAsPrimitive().getAsDouble();
-        double result;
-
-        if (operation == Operation.SIN) {
-            result = Math.sin(value);
-        } else if (operation == Operation.COS) {
-            result = Math.cos(value);
-        } else {
-            result = Math.tan(value);
-        }
-        in.addField(resultField, result);
-
-        out.collect(in);
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryController.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryController.java
deleted file mode 100644
index 29735c8..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryController.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.trigonometry;
-
-import org.apache.streampipes.client.StreamPipesClient;
-import org.apache.streampipes.container.config.ConfigExtractor;
-import org.apache.streampipes.model.DataProcessorType;
-import org.apache.streampipes.model.graph.DataProcessorDescription;
-import org.apache.streampipes.model.graph.DataProcessorInvocation;
-import org.apache.streampipes.model.schema.PropertyScope;
-import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
-import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
-import org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor;
-import org.apache.streampipes.sdk.helpers.*;
-import org.apache.streampipes.sdk.utils.Assets;
-import org.apache.streampipes.vocabulary.SO;
-import org.apache.streampipes.wrapper.flink.FlinkDataProcessorDeclarer;
-import org.apache.streampipes.wrapper.flink.FlinkDataProcessorRuntime;
-
-public class TrigonometryController extends FlinkDataProcessorDeclarer<TrigonometryParameters> {
-
-    private final String OPERAND = "operand";
-    private final String OPERATION = "operation";
-    private final String RESULT_FIELD = "trigonometryResult";
-
-
-    @Override
-    public DataProcessorDescription declareModel() {
-        return ProcessingElementBuilder.create("org.apache.streampipes.processors.enricher.flink.processor.trigonometry")
-                .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-                .withLocales(Locales.EN)
-                .category(DataProcessorType.ALGORITHM)
-                .requiredStream(StreamRequirementsBuilder
-                        .create()
-                        .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),
-                                Labels.withId(OPERAND),
-                                PropertyScope.NONE)
-                        .build())
-                .outputStrategy(
-                        OutputStrategies.append(
-                                EpProperties.numberEp(Labels.empty(), RESULT_FIELD, SO.Number)))
-                .requiredSingleValueSelection(Labels.withId(OPERATION),
-                        Options.from("sin(a)", "cos(a)", "tan(a)" ))
-                .build();
-    }
-
-    @Override
-    public FlinkDataProcessorRuntime<TrigonometryParameters> getRuntime(DataProcessorInvocation graph,
-                                                                        ProcessingElementParameterExtractor extractor,
-                                                                        ConfigExtractor configExtractor,
-                                                                        StreamPipesClient streamPipesClient) {
-        String operand = extractor.mappingPropertyValue(OPERAND);
-        String operation = extractor.selectedSingleValue(OPERATION, String.class);
-
-        Operation trigonometryFunction = null;
-        switch (operation) {
-            case "sin(a)": trigonometryFunction = Operation.SIN;
-                break;
-            case "cos(a)": trigonometryFunction = Operation.COS;
-                break;
-            case "tan(a)": trigonometryFunction = Operation.TAN;
-
-        }
-
-
-        TrigonometryParameters parameters = new TrigonometryParameters(graph, operand, trigonometryFunction, RESULT_FIELD);
-
-        return new TrigonometryProgram(parameters, configExtractor, streamPipesClient);
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryParameters.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryParameters.java
deleted file mode 100644
index 5c0d80c..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryParameters.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.trigonometry;
-
-import org.apache.streampipes.model.graph.DataProcessorInvocation;
-import org.apache.streampipes.wrapper.params.binding.EventProcessorBindingParams;
-
-public class TrigonometryParameters extends EventProcessorBindingParams {
-
-    private String operand;
-    private Operation operation;
-    private String resultField;
-
-    public TrigonometryParameters(DataProcessorInvocation graph, String operand, Operation operation, String resultField) {
-        super(graph);
-        this.operand = operand;
-        this.operation = operation;
-        this.resultField = resultField;
-    }
-
-    public String getOperand() {
-        return operand;
-    }
-
-    public Operation getOperation() {
-        return operation;
-    }
-
-    public String getResultField() {
-        return resultField;
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryProgram.java b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryProgram.java
deleted file mode 100644
index ceb2d83..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/TrigonometryProgram.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.processors.enricher.flink.processor.trigonometry;
-
-import org.apache.flink.streaming.api.datastream.DataStream;
-import org.apache.streampipes.client.StreamPipesClient;
-import org.apache.streampipes.container.config.ConfigExtractor;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.processors.enricher.flink.AbstractEnricherProgram;
-
-public class TrigonometryProgram extends AbstractEnricherProgram<TrigonometryParameters> {
-
-    public TrigonometryProgram(TrigonometryParameters params,
-                               ConfigExtractor configExtractor,
-                               StreamPipesClient streamPipesClient) {
-        super(params, configExtractor, streamPipesClient);
-    }
-
-    @Override
-    protected DataStream<Event> getApplicationLogic(DataStream<Event>... dataStreams) {
-        return dataStreams[0].flatMap(new Trigonometry(params.getOperand(), params.getOperation(), params.getResultField()));
-    }
-}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.mathop/strings.en b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.mathop/strings.en
deleted file mode 100644
index 877a15a..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.mathop/strings.en
+++ /dev/null
@@ -1,11 +0,0 @@
-org.apache.streampipes.processors.enricher.flink.processor.math.mathop.title=Math
-org.apache.streampipes.processors.enricher.flink.processor.math.mathop.description=Performs calculations on event properties (+, -, *, /, %)
-
-leftOperand.title=Left operand
-leftOperand.description=Select left operand
-
-rightOperand.title=Right operand
-rightOperand.description=Select right operand
-
-operation.title=Select Operation
-operation.description=
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop/strings.en b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop/strings.en
deleted file mode 100644
index 3825f6e..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop/strings.en
+++ /dev/null
@@ -1,10 +0,0 @@
-org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop.title=Static Math
-org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop.description=Performs calculation on an event property with a static value (+, -, *, /, %)
-
-leftOperand.title=Left operand
-leftOperand.description=Select left operand
-
-rightOperandValue.title=Right operand value
-rightOperandValue.description=Specify the value of the right operand.
-
-operation.title=Select operation
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.trigonometry/strings.en b/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.trigonometry/strings.en
deleted file mode 100644
index 051c848..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.trigonometry/strings.en
+++ /dev/null
@@ -1,9 +0,0 @@
-org.apache.streampipes.processors.enricher.flink.processor.trigonometry.title=Trigonometry Functions
-org.apache.streampipes.processors.enricher.flink.processor.trigonometry.description=Performs Trigonometric functions on event properties
-
-operand.title=Alpha
-operand.description=Select the alpha parameter
-
-operation.title=Operation
-operation.description=
-
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/Dockerfile b/streampipes-extensions/streampipes-processors-enricher-jvm/Dockerfile
deleted file mode 100644
index 63fe799..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk9-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-enricher-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-enricher-jvm/aarch64.Dockerfile
deleted file mode 100644
index dd6f1a3..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-enricher-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-processors-enricher-jvm/arm.Dockerfile
deleted file mode 100644
index 28cba17..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-enricher-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/development/.env b/streampipes-extensions/streampipes-processors-enricher-jvm/development/.env
deleted file mode 100644
index db69c0d..0000000
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/development/.env
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6015
-SP_HOST=host.docker.internal
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/pom.xml b/streampipes-extensions/streampipes-processors-enricher-jvm/pom.xml
index f383bba..0b4c4b4 100644
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/pom.xml
@@ -20,26 +20,22 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-processors-enricher-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.graalvm.js</groupId>
@@ -50,37 +46,4 @@
             <artifactId>js-scriptengine</artifactId>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-processors-enricher-jvm</finalName>
-
-    </build>
 </project>
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/EnricherJvmInit.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/EnricherJvmInit.java
index d022600..d18ece8 100644
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/EnricherJvmInit.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/EnricherJvmInit.java
@@ -29,7 +29,10 @@
 import org.apache.streampipes.messaging.kafka.SpKafkaProtocolFactory;
 import org.apache.streampipes.messaging.mqtt.SpMqttProtocolFactory;
 import org.apache.streampipes.processors.enricher.jvm.processor.jseval.JSEvalController;
+import org.apache.streampipes.processors.enricher.jvm.processor.math.MathOpProcessor;
+import org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop.StaticMathOpProcessor;
 import org.apache.streampipes.processors.enricher.jvm.processor.sizemeasure.SizeMeasureController;
+import org.apache.streampipes.processors.enricher.jvm.processor.trigonometry.TrigonometryProcessor;
 import org.apache.streampipes.processors.enricher.jvm.processor.valueChange.ValueChangeProcessor;
 
 public class EnricherJvmInit extends StandaloneModelSubmitter {
@@ -46,6 +49,9 @@
             8090)
             .registerPipelineElements(new SizeMeasureController(),
                     new JSEvalController(),
+                    new MathOpProcessor(),
+                    new StaticMathOpProcessor(),
+                    new TrigonometryProcessor(),
                     new ValueChangeProcessor())
             .registerMessagingFormats(
                     new JsonDataFormatFactory(),
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessor.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessor.java
new file mode 100644
index 0000000..0c54e49
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessor.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.processors.enricher.jvm.processor.math;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.model.DataProcessorType;
+import org.apache.streampipes.model.graph.DataProcessorDescription;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.processors.enricher.jvm.processor.math.operation.*;
+import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.helpers.*;
+import org.apache.streampipes.sdk.utils.Assets;
+import org.apache.streampipes.vocabulary.SO;
+import org.apache.streampipes.wrapper.context.EventProcessorRuntimeContext;
+import org.apache.streampipes.wrapper.routing.SpOutputCollector;
+import org.apache.streampipes.wrapper.standalone.ProcessorParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataProcessor;
+
+public class MathOpProcessor extends StreamPipesDataProcessor {
+
+  private final String RESULT_FIELD = "calculationResult";
+  private final String LEFT_OPERAND = "leftOperand";
+  private final String RIGHT_OPERAND = "rightOperand";
+  private final String OPERATION = "operation";
+
+  Operation arithmeticOperation = null;
+  String leftOperand;
+  String rightOperand;
+
+  @Override
+  public DataProcessorDescription declareModel() {
+    return ProcessingElementBuilder.create("org.apache.streampipes.processors.enricher.jvm.processor.math.mathop")
+      .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+      .withLocales(Locales.EN)
+      .category(DataProcessorType.ALGORITHM)
+      .requiredStream(StreamRequirementsBuilder
+        .create()
+        .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),
+          Labels.withId(LEFT_OPERAND),
+          PropertyScope.NONE)
+        .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),
+          Labels.withId(RIGHT_OPERAND),
+          PropertyScope.NONE)
+        .build())
+      .outputStrategy(
+        OutputStrategies.append(
+          EpProperties.numberEp(Labels.empty(), RESULT_FIELD, SO.Number)))
+      .requiredSingleValueSelection(Labels.withId(OPERATION), Options.from("+", "-", "/",
+        "*", "%"))
+      .build();
+  }
+
+  @Override
+  public void onInvocation(ProcessorParams parameters, SpOutputCollector spOutputCollector, EventProcessorRuntimeContext runtimeContext) throws SpRuntimeException {
+    this.leftOperand = parameters.extractor().mappingPropertyValue(LEFT_OPERAND);
+    this.rightOperand = parameters.extractor().mappingPropertyValue(RIGHT_OPERAND);
+    String operation = parameters.extractor().selectedSingleValue(OPERATION, String.class);
+
+    switch (operation) {
+      case "+":
+        arithmeticOperation = new OperationAddition();
+        break;
+      case "-":
+        arithmeticOperation = new OperationSubtracting();
+        break;
+      case "*":
+        arithmeticOperation = new OperationMultiply();
+        break;
+      case "/":
+        arithmeticOperation = new OperationDivide();
+        break;
+      case "%":
+        arithmeticOperation = new OperationModulo();
+    }
+  }
+
+  @Override
+  public void onEvent(Event in, SpOutputCollector out) throws SpRuntimeException {
+    Double leftValue  = in.getFieldBySelector(leftOperand).getAsPrimitive().getAsDouble();
+    Double rightValue = in.getFieldBySelector(rightOperand).getAsPrimitive().getAsDouble();
+
+    Double result = arithmeticOperation.operate(leftValue, rightValue);
+    in.addField(RESULT_FIELD, result);
+
+    out.collect(in);
+  }
+
+  @Override
+  public void onDetach() throws SpRuntimeException {
+
+  }
+}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/Operation.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/Operation.java
similarity index 91%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/Operation.java
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/Operation.java
index e9cd593..f3d71bc 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/Operation.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/Operation.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.math.operation;
+package org.apache.streampipes.processors.enricher.jvm.processor.math.operation;
 
 import java.io.Serializable;
 
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationAddition.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationAddition.java
similarity index 91%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationAddition.java
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationAddition.java
index 8a19293..b3e8507 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationAddition.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationAddition.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.math.operation;
+package org.apache.streampipes.processors.enricher.jvm.processor.math.operation;
 
 public class OperationAddition implements Operation {
 
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationDivide.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationDivide.java
similarity index 91%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationDivide.java
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationDivide.java
index b648a20..e60c610 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationDivide.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationDivide.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.math.operation;
+package org.apache.streampipes.processors.enricher.jvm.processor.math.operation;
 
 public class OperationDivide implements Operation {
 
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationModulo.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationModulo.java
similarity index 91%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationModulo.java
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationModulo.java
index ab50adf..0561722 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationModulo.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationModulo.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.math.operation;
+package org.apache.streampipes.processors.enricher.jvm.processor.math.operation;
 
 public class OperationModulo implements Operation {
 
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationMultiply.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationMultiply.java
similarity index 91%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationMultiply.java
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationMultiply.java
index e359244..f8d121e 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationMultiply.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationMultiply.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.math.operation;
+package org.apache.streampipes.processors.enricher.jvm.processor.math.operation;
 
 public class OperationMultiply implements Operation{
 
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationSubtracting.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationSubtracting.java
similarity index 91%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationSubtracting.java
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationSubtracting.java
index 27163a4..d8ed36d 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/OperationSubtracting.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/operation/OperationSubtracting.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.math.operation;
+package org.apache.streampipes.processors.enricher.jvm.processor.math.operation;
 
 public class OperationSubtracting implements Operation {
 
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/staticmathop/StaticMathOpProcessor.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/staticmathop/StaticMathOpProcessor.java
new file mode 100644
index 0000000..3fe76bc
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/staticmathop/StaticMathOpProcessor.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.model.DataProcessorType;
+import org.apache.streampipes.model.graph.DataProcessorDescription;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.processors.enricher.jvm.processor.math.operation.*;
+import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.helpers.*;
+import org.apache.streampipes.sdk.utils.Assets;
+import org.apache.streampipes.wrapper.context.EventProcessorRuntimeContext;
+import org.apache.streampipes.wrapper.routing.SpOutputCollector;
+import org.apache.streampipes.wrapper.standalone.ProcessorParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataProcessor;
+
+public class StaticMathOpProcessor extends StreamPipesDataProcessor {
+
+  private final String RESULT_FIELD = "calculationResultStatic";
+  private final String LEFT_OPERAND = "leftOperand";
+  private final String RIGHT_OPERAND_VALUE = "rightOperandValue";
+  private final String OPERATION = "operation";
+
+  Operation arithmeticOperation;
+  String leftOperand;
+  double rightOperandValue;
+
+
+  @Override
+  public DataProcessorDescription declareModel() {
+    return ProcessingElementBuilder.create("org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop")
+      .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+      .withLocales(Locales.EN)
+      .category(DataProcessorType.ALGORITHM)
+      .requiredStream(StreamRequirementsBuilder
+        .create()
+        .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),
+          Labels.withId(LEFT_OPERAND),
+          PropertyScope.NONE)
+        .build())
+      .requiredFloatParameter(Labels.withId(RIGHT_OPERAND_VALUE))
+      .outputStrategy(
+        OutputStrategies.keep())
+      .requiredSingleValueSelection(Labels.withId(OPERATION),
+        Options.from("+", "-", "/", "*", "%"))
+      .build();
+  }
+
+  @Override
+  public void onInvocation(ProcessorParams parameters, SpOutputCollector spOutputCollector, EventProcessorRuntimeContext runtimeContext) throws SpRuntimeException {
+    this.leftOperand = parameters.extractor().mappingPropertyValue(LEFT_OPERAND);
+    this.rightOperandValue = parameters.extractor().singleValueParameter(RIGHT_OPERAND_VALUE, Double.class);
+    String operation = parameters.extractor().selectedSingleValue(OPERATION, String.class);
+
+    switch (operation) {
+      case "+":
+        arithmeticOperation = new OperationAddition();
+        break;
+      case "-":
+        arithmeticOperation = new OperationSubtracting();
+        break;
+      case "*":
+        arithmeticOperation = new OperationMultiply();
+        break;
+      case "/":
+        arithmeticOperation = new OperationDivide();
+        break;
+      case "%":
+        arithmeticOperation = new OperationModulo();
+    }
+  }
+
+  @Override
+  public void onEvent(Event in, SpOutputCollector out) throws SpRuntimeException {
+    Double leftValue  = Double.parseDouble(String.valueOf(in.getFieldBySelector(leftOperand)
+      .getAsPrimitive().getAsDouble()));
+
+    Double result = arithmeticOperation.operate(leftValue, rightOperandValue);
+    in.updateFieldBySelector(leftOperand, result);
+
+    out.collect(in);
+  }
+
+  @Override
+  public void onDetach() throws SpRuntimeException {
+
+  }
+}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/Operation.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/trigonometry/Operation.java
similarity index 91%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/Operation.java
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/trigonometry/Operation.java
index 794a000..c2c179a 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/trigonometry/Operation.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/trigonometry/Operation.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.trigonometry;
+package org.apache.streampipes.processors.enricher.jvm.processor.trigonometry;
 
 public enum Operation {
     SIN,
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/trigonometry/TrigonometryProcessor.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/trigonometry/TrigonometryProcessor.java
new file mode 100644
index 0000000..3067168
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/trigonometry/TrigonometryProcessor.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.processors.enricher.jvm.processor.trigonometry;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.model.DataProcessorType;
+import org.apache.streampipes.model.graph.DataProcessorDescription;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.helpers.*;
+import org.apache.streampipes.sdk.utils.Assets;
+import org.apache.streampipes.vocabulary.SO;
+import org.apache.streampipes.wrapper.context.EventProcessorRuntimeContext;
+import org.apache.streampipes.wrapper.routing.SpOutputCollector;
+import org.apache.streampipes.wrapper.standalone.ProcessorParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataProcessor;
+
+public class TrigonometryProcessor extends StreamPipesDataProcessor {
+
+  private final String OPERAND = "operand";
+  private final String OPERATION = "operation";
+  private final String RESULT_FIELD = "trigonometryResult";
+
+  private Operation operation;
+  private String operand;
+
+
+  @Override
+  public DataProcessorDescription declareModel() {
+    return ProcessingElementBuilder.create("org.apache.streampipes.processors.enricher.jvm.processor.trigonometry")
+      .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+      .withLocales(Locales.EN)
+      .category(DataProcessorType.ALGORITHM)
+      .requiredStream(StreamRequirementsBuilder
+        .create()
+        .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),
+          Labels.withId(OPERAND),
+          PropertyScope.NONE)
+        .build())
+      .outputStrategy(
+        OutputStrategies.append(
+          EpProperties.numberEp(Labels.empty(), RESULT_FIELD, SO.Number)))
+      .requiredSingleValueSelection(Labels.withId(OPERATION),
+        Options.from("sin", "cos", "tan" ))
+      .build();
+  }
+
+  @Override
+  public void onInvocation(ProcessorParams parameters,
+                           SpOutputCollector spOutputCollector,
+                           EventProcessorRuntimeContext runtimeContext) throws SpRuntimeException {
+
+    this.operand = parameters.extractor().mappingPropertyValue(OPERAND);
+    String stringOperation = parameters.extractor().selectedSingleValue(OPERATION, String.class);
+
+    switch (stringOperation) {
+      case "sin": operation = Operation.SIN;
+        break;
+      case "cos": operation = Operation.COS;
+        break;
+      case "tan": operation = Operation.TAN;
+
+    }
+  }
+
+  @Override
+  public void onEvent(Event in, SpOutputCollector out) throws SpRuntimeException {
+    double value = in.getFieldBySelector(operand).getAsPrimitive().getAsDouble();
+    double result;
+
+    if (operation == Operation.SIN) {
+      result = Math.sin(value);
+    } else if (operation == Operation.COS) {
+      result = Math.cos(value);
+    } else {
+      result = Math.tan(value);
+    }
+    in.addField(RESULT_FIELD, result);
+
+    out.collect(in);
+  }
+
+  @Override
+  public void onDetach() throws SpRuntimeException {
+
+  }
+}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.mathop/documentation.md b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.mathop/documentation.md
similarity index 100%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.mathop/documentation.md
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.mathop/documentation.md
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.mathop/icon.png b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.mathop/icon.png
similarity index 100%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.mathop/icon.png
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.mathop/icon.png
Binary files differ
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.mathop/strings.en b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.mathop/strings.en
new file mode 100644
index 0000000..d55af60
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.mathop/strings.en
@@ -0,0 +1,11 @@
+org.apache.streampipes.processors.enricher.jvm.processor.math.mathop.title=Math
+org.apache.streampipes.processors.enricher.jvm.processor.math.mathop.description=Performs calculations on event properties (+, -, *, /, %)
+
+leftOperand.title=Left operand
+leftOperand.description=Select left operand
+
+rightOperand.title=Right operand
+rightOperand.description=Select right operand
+
+operation.title=Select Operation
+operation.description=
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop/documentation.md b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop/documentation.md
similarity index 100%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop/documentation.md
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop/documentation.md
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop/icon.png b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop/icon.png
similarity index 100%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.math.staticmathop/icon.png
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop/icon.png
Binary files differ
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop/strings.en b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop/strings.en
new file mode 100644
index 0000000..8c3c82b
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop/strings.en
@@ -0,0 +1,10 @@
+org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop.title=Static Math
+org.apache.streampipes.processors.enricher.jvm.processor.math.staticmathop.description=Performs calculation on an event property with a static value (+, -, *, /, %)
+
+leftOperand.title=Left operand
+leftOperand.description=Select left operand
+
+rightOperandValue.title=Right operand value
+rightOperandValue.description=Specify the value of the right operand.
+
+operation.title=Select operation
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.trigonometry/documentation.md b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.trigonometry/documentation.md
similarity index 100%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.trigonometry/documentation.md
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.trigonometry/documentation.md
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.trigonometry/icon.png b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.trigonometry/icon.png
similarity index 100%
rename from streampipes-extensions/streampipes-processors-enricher-flink/src/main/resources/org.apache.streampipes.processors.enricher.flink.processor.trigonometry/icon.png
rename to streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.trigonometry/icon.png
Binary files differ
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.trigonometry/strings.en b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.trigonometry/strings.en
new file mode 100644
index 0000000..7280fa9
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/resources/org.apache.streampipes.processors.enricher.jvm.processor.trigonometry/strings.en
@@ -0,0 +1,9 @@
+org.apache.streampipes.processors.enricher.jvm.processor.trigonometry.title=Trigonometry Functions
+org.apache.streampipes.processors.enricher.jvm.processor.trigonometry.description=Performs Trigonometric functions on event properties
+
+operand.title=Alpha
+operand.description=Select the alpha parameter
+
+operation.title=Operation
+operation.description=
+
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/Dockerfile b/streampipes-extensions/streampipes-processors-filters-jvm/Dockerfile
deleted file mode 100644
index f2b8798..0000000
--- a/streampipes-extensions/streampipes-processors-filters-jvm/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-filters-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-filters-jvm/aarch64.Dockerfile
deleted file mode 100644
index e835ef3..0000000
--- a/streampipes-extensions/streampipes-processors-filters-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-filters-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-processors-filters-jvm/arm.Dockerfile
deleted file mode 100644
index 692ddb3..0000000
--- a/streampipes-extensions/streampipes-processors-filters-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-filters-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/development/env b/streampipes-extensions/streampipes-processors-filters-jvm/development/env
deleted file mode 100644
index 28f3dca..0000000
--- a/streampipes-extensions/streampipes-processors-filters-jvm/development/env
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6015
-#SP_HOST=localhost
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml b/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
index 9d12a29..c0a63ed 100644
--- a/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
@@ -21,64 +21,27 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-processors-filters-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.quartz-scheduler</groupId>
             <artifactId>quartz</artifactId>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-processors-filters-jvm</finalName>
-
-    </build>
 </project>
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/numericaltextfilter/NumericalTextFilterProcessor.java b/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/numericaltextfilter/NumericalTextFilterProcessor.java
index a41ef2d..dad2e6a 100644
--- a/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/numericaltextfilter/NumericalTextFilterProcessor.java
+++ b/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/numericaltextfilter/NumericalTextFilterProcessor.java
@@ -71,7 +71,7 @@
             .requiredFloatParameter(Labels.withId(NUMBER_VALUE), NUMBER_MAPPING)
             .requiredSingleValueSelection(Labels.withId(TEXT_OPERATION), Options.from("MATCHES",
                     "CONTAINS"))
-            .requiredTextParameter(Labels.withId(TEXT_KEYWORD), "text")
+            .requiredTextParameterWithLink(Labels.withId(TEXT_KEYWORD), "text")
             .outputStrategy(OutputStrategies.keep())
             .build();
 
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/textfilter/TextFilterProcessor.java b/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/textfilter/TextFilterProcessor.java
index 855fba9..8e29c45 100644
--- a/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/textfilter/TextFilterProcessor.java
+++ b/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/textfilter/TextFilterProcessor.java
@@ -59,7 +59,7 @@
                     .build())
             .requiredSingleValueSelection(Labels.withId(OPERATION_ID), Options.from("MATCHES",
                     "CONTAINS"))
-            .requiredTextParameter(Labels.withId(KEYWORD_ID), "text")
+            .requiredTextParameterWithLink(Labels.withId(KEYWORD_ID), "text")
             .outputStrategy(OutputStrategies.keep())
             .build();
   }
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/Dockerfile b/streampipes-extensions/streampipes-processors-filters-siddhi/Dockerfile
deleted file mode 100644
index 806bb28..0000000
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-filters-siddhi.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-filters-siddhi/aarch64.Dockerfile
deleted file mode 100644
index 58bc359..0000000
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-filters-siddhi.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/arm.Dockerfile b/streampipes-extensions/streampipes-processors-filters-siddhi/arm.Dockerfile
deleted file mode 100644
index ce43076..0000000
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-filters-siddhi.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/development/env b/streampipes-extensions/streampipes-processors-filters-siddhi/development/env
index dfa6559..869b1d3 100644
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/development/env
+++ b/streampipes-extensions/streampipes-processors-filters-siddhi/development/env
@@ -16,4 +16,4 @@
 # Those parameters are used by IntelliJ to set the default consul parameters for development
 SP_PORT=6020
 SP_HOST=host.docker.internal
-SP_DEBUG=true
+SP_DEBUG=true
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/pom.xml b/streampipes-extensions/streampipes-processors-filters-siddhi/pom.xml
index f09400b..0a7c7ca 100644
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/pom.xml
+++ b/streampipes-extensions/streampipes-processors-filters-siddhi/pom.xml
@@ -21,27 +21,23 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-processors-filters-siddhi</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-siddhi</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.slf4j</groupId>
@@ -70,43 +66,8 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-test-utils</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-processors-filters-siddhi</finalName>
-
-    </build>
-
-
 </project>
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/count/CountAggregation.java b/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/count/CountAggregation.java
index 1842a58..9bf37f5 100644
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/count/CountAggregation.java
+++ b/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/count/CountAggregation.java
@@ -40,6 +40,7 @@
 public class CountAggregation extends StreamPipesSiddhiProcessor {
 
   private static final String TIME_WINDOW_KEY = "time-window";
+  private static final String TIMESTAMP_MAPPING_KEY = "timestamp-mapping";
   private static final String SCALE_KEY = "scale";
   private static final String COUNT_MAPPING = "count-mapping";
 
@@ -55,8 +56,14 @@
             .withLocales(Locales.EN)
             .requiredStream(StreamRequirementsBuilder
                     .create()
-                    .requiredPropertyWithUnaryMapping(EpRequirements.anyProperty(),
-                            Labels.withId(COUNT_MAPPING), PropertyScope.DIMENSION_PROPERTY)
+                    .requiredPropertyWithUnaryMapping(
+                      EpRequirements.timestampReq(),
+                      Labels.withId(TIMESTAMP_MAPPING_KEY),
+                      PropertyScope.NONE)
+                    .requiredPropertyWithUnaryMapping(
+                      EpRequirements.anyProperty(),
+                      Labels.withId(COUNT_MAPPING),
+                      PropertyScope.DIMENSION_PROPERTY)
                     .build())
             .outputStrategy(OutputStrategies.fixed(
                     EpProperties.timestampProperty("timestamp"),
@@ -76,12 +83,14 @@
     Integer timeWindowSize = siddhiParams.getParams().extractor().singleValueParameter(TIME_WINDOW_KEY, Integer.class);
     String scale = siddhiParams.getParams().extractor().selectedSingleValueInternalName(SCALE_KEY, String.class);
     String fieldToCount = siddhiParams.getParams().extractor().mappingPropertyValue(COUNT_MAPPING);
+    String timestampField = siddhiParams.getParams().extractor().mappingPropertyValue(TIMESTAMP_MAPPING_KEY);
+
 
     FromClause fromClause = FromClause.create();
     fromClause.add(Expressions.stream(siddhiParams.getInputStreamNames().get(0), Expressions.timeWindow(timeWindowSize, toTimeUnit(scale))));
 
     SelectClause selectClause = SelectClause.create(
-            Expressions.as(Expressions.property("currentTimeMillis()"), "timestamp"),
+            Expressions.as(Expressions.property(timestampField), "timestamp"),
             Expressions.as(Expressions.property(fieldToCount), "value"),
             Expressions.as(Expressions.count(Expressions.property(fieldToCount)), "count"));
 
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/resources/org.apache.streampipes.processors.siddhi.count/strings.en b/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/resources/org.apache.streampipes.processors.siddhi.count/strings.en
index ce1c093..e5e690a 100644
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/resources/org.apache.streampipes.processors.siddhi.count/strings.en
+++ b/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/resources/org.apache.streampipes.processors.siddhi.count/strings.en
@@ -9,3 +9,6 @@
 
 scale.title=Time Window Scale
 scale.description=
+
+timestamp-mapping.title=Timestamp Field
+timestamp-mapping.description=The value which contains a timestamp
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-geo-flink/Dockerfile b/streampipes-extensions/streampipes-processors-geo-flink/Dockerfile
deleted file mode 100644
index ab39bee..0000000
--- a/streampipes-extensions/streampipes-processors-geo-flink/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-geo-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-geo-flink/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-geo-flink/aarch64.Dockerfile
deleted file mode 100644
index f26c8d2..0000000
--- a/streampipes-extensions/streampipes-processors-geo-flink/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-geo-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-geo-flink/arm.Dockerfile b/streampipes-extensions/streampipes-processors-geo-flink/arm.Dockerfile
deleted file mode 100644
index 3730ca5..0000000
--- a/streampipes-extensions/streampipes-processors-geo-flink/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-geo-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-geo-flink/development/env b/streampipes-extensions/streampipes-processors-geo-flink/development/env
deleted file mode 100644
index 4dfff09..0000000
--- a/streampipes-extensions/streampipes-processors-geo-flink/development/env
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6025
-SP_HOST=host.docker.internal
-SP_DEBUG=true
-SP_FLINK_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-geo-flink/pom.xml b/streampipes-extensions/streampipes-processors-geo-flink/pom.xml
index 1a09e5a..d0fc406 100644
--- a/streampipes-extensions/streampipes-processors-geo-flink/pom.xml
+++ b/streampipes-extensions/streampipes-processors-geo-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -36,12 +36,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/streampipes-extensions/streampipes-processors-geo-jvm/Dockerfile b/streampipes-extensions/streampipes-processors-geo-jvm/Dockerfile
deleted file mode 100644
index e66211b..0000000
--- a/streampipes-extensions/streampipes-processors-geo-jvm/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-geo-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-geo-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-geo-jvm/aarch64.Dockerfile
deleted file mode 100644
index 9a33a1b..0000000
--- a/streampipes-extensions/streampipes-processors-geo-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-geo-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-geo-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-processors-geo-jvm/arm.Dockerfile
deleted file mode 100644
index fc2707c..0000000
--- a/streampipes-extensions/streampipes-processors-geo-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-geo-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-geo-jvm/development/env b/streampipes-extensions/streampipes-processors-geo-jvm/development/env
deleted file mode 100644
index 3e9e217..0000000
--- a/streampipes-extensions/streampipes-processors-geo-jvm/development/env
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=8005
-SP_HOST=172.17.0.1
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-geo-jvm/pom.xml b/streampipes-extensions/streampipes-processors-geo-jvm/pom.xml
index 861e1d9..19c70e4 100644
--- a/streampipes-extensions/streampipes-processors-geo-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-geo-jvm/pom.xml
@@ -21,32 +21,28 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-processors-geo-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -69,38 +65,4 @@
             <version>1.16.1</version>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-processors-geo-jvm</finalName>
-
-    </build>
-
 </project>
diff --git a/streampipes-extensions/streampipes-processors-geo-jvm/src/main/java/org/apache/streampipes/processors/geo/jvm/GeoJvmInit.java b/streampipes-extensions/streampipes-processors-geo-jvm/src/main/java/org/apache/streampipes/processors/geo/jvm/GeoJvmInit.java
index 2d86d13..9498870 100644
--- a/streampipes-extensions/streampipes-processors-geo-jvm/src/main/java/org/apache/streampipes/processors/geo/jvm/GeoJvmInit.java
+++ b/streampipes-extensions/streampipes-processors-geo-jvm/src/main/java/org/apache/streampipes/processors/geo/jvm/GeoJvmInit.java
@@ -41,10 +41,6 @@
 
 public class GeoJvmInit extends StandaloneModelSubmitter {
 
-  public static void main(String[] args) {
-    new GeoJvmInit().init();
-  }
-
   @Override
   public SpServiceDefinition provideServiceDefinition() {
     return SpServiceDefinitionBuilder.create("org.apache.streampipes.processors.geo.jvm",
diff --git a/streampipes-extensions/streampipes-processors-image-processing-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-image-processing-jvm/aarch64.Dockerfile
deleted file mode 100644
index 3659bbc..0000000
--- a/streampipes-extensions/streampipes-processors-image-processing-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-image-processing-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-image-processing-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-processors-image-processing-jvm/arm.Dockerfile
deleted file mode 100644
index 14917a2..0000000
--- a/streampipes-extensions/streampipes-processors-image-processing-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-image-processing-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-image-processing-jvm/development/env b/streampipes-extensions/streampipes-processors-image-processing-jvm/development/env
deleted file mode 100644
index 3e5fb41..0000000
--- a/streampipes-extensions/streampipes-processors-image-processing-jvm/development/env
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6035
-SP_HOST=host.docker.internal
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-image-processing-jvm/pom.xml b/streampipes-extensions/streampipes-processors-image-processing-jvm/pom.xml
index 6332393..e160301 100644
--- a/streampipes-extensions/streampipes-processors-image-processing-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-image-processing-jvm/pom.xml
@@ -21,27 +21,23 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-processors-image-processing-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -56,37 +52,4 @@
             <artifactId>ddogleg</artifactId>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-processors-image-processing-jvm</finalName>
-    </build>
-
 </project>
diff --git a/streampipes-extensions/streampipes-processors-image-processing-jvm/src/main/java/org/apache/streampipes/processors/imageprocessing/jvm/ImageProcessingJvmInit.java b/streampipes-extensions/streampipes-processors-image-processing-jvm/src/main/java/org/apache/streampipes/processors/imageprocessing/jvm/ImageProcessingJvmInit.java
index 0f0c136..22f9897 100644
--- a/streampipes-extensions/streampipes-processors-image-processing-jvm/src/main/java/org/apache/streampipes/processors/imageprocessing/jvm/ImageProcessingJvmInit.java
+++ b/streampipes-extensions/streampipes-processors-image-processing-jvm/src/main/java/org/apache/streampipes/processors/imageprocessing/jvm/ImageProcessingJvmInit.java
@@ -35,10 +35,6 @@
 
 public class ImageProcessingJvmInit extends StandaloneModelSubmitter {
 
-  public static void main(String[] args) {
-    new ImageProcessingJvmInit().init();
-  }
-
   @Override
   public SpServiceDefinition provideServiceDefinition() {
     return SpServiceDefinitionBuilder.create("org.apache.streampipes.processors.imageprocessing.jvm",
diff --git a/streampipes-extensions/streampipes-processors-pattern-detection-flink/Dockerfile b/streampipes-extensions/streampipes-processors-pattern-detection-flink/Dockerfile
deleted file mode 100644
index 600ef8b..0000000
--- a/streampipes-extensions/streampipes-processors-pattern-detection-flink/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-pattern-detection-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-pattern-detection-flink/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-pattern-detection-flink/aarch64.Dockerfile
deleted file mode 100644
index f5ac542..0000000
--- a/streampipes-extensions/streampipes-processors-pattern-detection-flink/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-pattern-detection-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-pattern-detection-flink/arm.Dockerfile b/streampipes-extensions/streampipes-processors-pattern-detection-flink/arm.Dockerfile
deleted file mode 100644
index 144c755..0000000
--- a/streampipes-extensions/streampipes-processors-pattern-detection-flink/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-pattern-detection-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-pattern-detection-flink/development/env b/streampipes-extensions/streampipes-processors-pattern-detection-flink/development/env
deleted file mode 100644
index 7350282..0000000
--- a/streampipes-extensions/streampipes-processors-pattern-detection-flink/development/env
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6040
-SP_HOST=host.docker.internal
-SP_DEBUG=true
-SP_FLINK_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-pattern-detection-flink/pom.xml b/streampipes-extensions/streampipes-processors-pattern-detection-flink/pom.xml
index f6c5b77..f917cf3 100644
--- a/streampipes-extensions/streampipes-processors-pattern-detection-flink/pom.xml
+++ b/streampipes-extensions/streampipes-processors-pattern-detection-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -37,12 +37,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>log4j</groupId>
@@ -112,7 +112,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-test-utils</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
@@ -157,5 +157,4 @@
         </plugins>
         <finalName>streampipes-processors-pattern-detection-flink</finalName>
     </build>
-
 </project>
diff --git a/streampipes-extensions/streampipes-processors-statistics-flink/Dockerfile b/streampipes-extensions/streampipes-processors-statistics-flink/Dockerfile
deleted file mode 100644
index f2fcb8e..0000000
--- a/streampipes-extensions/streampipes-processors-statistics-flink/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-statistics-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-statistics-flink/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-statistics-flink/aarch64.Dockerfile
deleted file mode 100644
index 6fca3bf..0000000
--- a/streampipes-extensions/streampipes-processors-statistics-flink/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-statistics-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-statistics-flink/arm.Dockerfile b/streampipes-extensions/streampipes-processors-statistics-flink/arm.Dockerfile
deleted file mode 100644
index 4fe36a0..0000000
--- a/streampipes-extensions/streampipes-processors-statistics-flink/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-statistics-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-statistics-flink/development/.env b/streampipes-extensions/streampipes-processors-statistics-flink/development/.env
deleted file mode 100644
index e5c610f..0000000
--- a/streampipes-extensions/streampipes-processors-statistics-flink/development/.env
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6045
-SP_HOST=host.docker.internal
-SP_DEBUG=true
-SP_FLINK_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-statistics-flink/pom.xml b/streampipes-extensions/streampipes-processors-statistics-flink/pom.xml
index 5147355..c984827 100644
--- a/streampipes-extensions/streampipes-processors-statistics-flink/pom.xml
+++ b/streampipes-extensions/streampipes-processors-statistics-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -36,12 +36,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-extensions/streampipes-processors-text-mining-flink/development/env b/streampipes-extensions/streampipes-processors-text-mining-flink/development/env
deleted file mode 100644
index 3e94b17..0000000
--- a/streampipes-extensions/streampipes-processors-text-mining-flink/development/env
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6050
-SP_HOST=host.docker.internal
-SP_DEBUG=true
-SP_FLINK_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-text-mining-flink/pom.xml b/streampipes-extensions/streampipes-processors-text-mining-flink/pom.xml
index bd95858..3411d6e 100644
--- a/streampipes-extensions/streampipes-processors-text-mining-flink/pom.xml
+++ b/streampipes-extensions/streampipes-processors-text-mining-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -36,12 +36,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -89,7 +89,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-test-utils</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/streampipes-extensions/streampipes-processors-text-mining-jvm/Dockerfile b/streampipes-extensions/streampipes-processors-text-mining-jvm/Dockerfile
deleted file mode 100644
index 4a0eed6..0000000
--- a/streampipes-extensions/streampipes-processors-text-mining-jvm/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-text-mining-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-text-mining-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-text-mining-jvm/aarch64.Dockerfile
deleted file mode 100644
index 302c873..0000000
--- a/streampipes-extensions/streampipes-processors-text-mining-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-text-mining-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-text-mining-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-processors-text-mining-jvm/arm.Dockerfile
deleted file mode 100644
index 3e110c7..0000000
--- a/streampipes-extensions/streampipes-processors-text-mining-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-text-mining-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-text-mining-jvm/development/env b/streampipes-extensions/streampipes-processors-text-mining-jvm/development/env
deleted file mode 100644
index fbb93b2..0000000
--- a/streampipes-extensions/streampipes-processors-text-mining-jvm/development/env
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6065
-SP_HOST=host.docker.internal
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-text-mining-jvm/pom.xml b/streampipes-extensions/streampipes-processors-text-mining-jvm/pom.xml
index f021fe0..8afccf5 100644
--- a/streampipes-extensions/streampipes-processors-text-mining-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-text-mining-jvm/pom.xml
@@ -21,27 +21,23 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-processors-text-mining-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -52,39 +48,8 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-mqtt</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-processors-text-mining-jvm</finalName>
-    </build>
 </project>
diff --git a/streampipes-extensions/streampipes-processors-transformation-flink/Dockerfile b/streampipes-extensions/streampipes-processors-transformation-flink/Dockerfile
deleted file mode 100644
index cbe76f3..0000000
--- a/streampipes-extensions/streampipes-processors-transformation-flink/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-transformation-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-transformation-flink/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-transformation-flink/aarch64.Dockerfile
deleted file mode 100644
index 1eb794c..0000000
--- a/streampipes-extensions/streampipes-processors-transformation-flink/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-transformation-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-transformation-flink/arm.Dockerfile b/streampipes-extensions/streampipes-processors-transformation-flink/arm.Dockerfile
deleted file mode 100644
index f92454a..0000000
--- a/streampipes-extensions/streampipes-processors-transformation-flink/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-transformation-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-transformation-flink/development/env b/streampipes-extensions/streampipes-processors-transformation-flink/development/env
deleted file mode 100644
index dc98a5d..0000000
--- a/streampipes-extensions/streampipes-processors-transformation-flink/development/env
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=6055
-SP_HOST=localhost
-SP_FLINK_DEBUG=true
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-transformation-flink/pom.xml b/streampipes-extensions/streampipes-processors-transformation-flink/pom.xml
index a4b4d59..a16d662 100644
--- a/streampipes-extensions/streampipes-processors-transformation-flink/pom.xml
+++ b/streampipes-extensions/streampipes-processors-transformation-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -36,17 +36,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-measurement-units</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -82,7 +82,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-test-utils</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -132,5 +132,4 @@
         </plugins>
         <finalName>streampipes-processors-transformation-flink</finalName>
     </build>
-
 </project>
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/Dockerfile b/streampipes-extensions/streampipes-processors-transformation-jvm/Dockerfile
deleted file mode 100644
index 55c3d34..0000000
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-processors-transformation-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-processors-transformation-jvm/aarch64.Dockerfile
deleted file mode 100644
index cde1ab7..0000000
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-processors-transformation-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-processors-transformation-jvm/arm.Dockerfile
deleted file mode 100644
index 6f7f281..0000000
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-processors-transformation-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/development/env b/streampipes-extensions/streampipes-processors-transformation-jvm/development/env
deleted file mode 100644
index 10821f4..0000000
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/development/env
+++ /dev/null
@@ -1,18 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-SP_PORT=6060
-SP_HOST=localhost
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/pom.xml b/streampipes-extensions/streampipes-processors-transformation-jvm/pom.xml
index 37f754e..db7e924 100644
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/pom.xml
@@ -21,16 +21,12 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-processors-transformation-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- External dependencies -->
         <dependency>
@@ -44,48 +40,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                        <configuration>
-                            <mainClass>org.apache.streampipes.processors.transformation.jvm.TransformationJvmInit</mainClass>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-processors-transformation-jvm</finalName>
-
-    </build>
 </project>
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/TransformationJvmInit.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/TransformationJvmInit.java
index a7d637d..f50421b 100644
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/TransformationJvmInit.java
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/TransformationJvmInit.java
@@ -39,6 +39,9 @@
 import org.apache.streampipes.processors.transformation.jvm.processor.booloperator.timer.BooleanTimerController;
 import org.apache.streampipes.processors.transformation.jvm.processor.csvmetadata.CsvMetadataEnrichmentController;
 import org.apache.streampipes.processors.transformation.jvm.processor.fieldrename.FiledRenameProcessor;
+import org.apache.streampipes.processors.transformation.jvm.processor.hasher.FieldHasherProcessor;
+import org.apache.streampipes.processors.transformation.jvm.processor.mapper.FieldMapperProcessor;
+import org.apache.streampipes.processors.transformation.jvm.processor.measurementconverter.MeasurementUnitConverterProcessor;
 import org.apache.streampipes.processors.transformation.jvm.processor.state.labeler.number.NumberLabelerController;
 import org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.counter.StringCounterController;
 import org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.state.StringToStateController;
@@ -72,6 +75,9 @@
                     new BooleanTimekeepingController(),
                     new BooleanTimerController(),
                     new CsvMetadataEnrichmentController(),
+                    new FieldHasherProcessor(),
+                    new FieldMapperProcessor(),
+                    new MeasurementUnitConverterProcessor(),
                     new TaskDurationController(),
                     new TransformToBooleanController(),
                     new StringTimerController(),
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/FieldHasherProcessor.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/FieldHasherProcessor.java
new file mode 100644
index 0000000..e13decd
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/FieldHasherProcessor.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.processors.transformation.jvm.processor.hasher;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.model.graph.DataProcessorDescription;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.processors.transformation.jvm.processor.hasher.algorithm.HashAlgorithm;
+import org.apache.streampipes.processors.transformation.jvm.processor.hasher.algorithm.HashAlgorithmType;
+import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.helpers.*;
+import org.apache.streampipes.sdk.utils.Assets;
+import org.apache.streampipes.wrapper.context.EventProcessorRuntimeContext;
+import org.apache.streampipes.wrapper.routing.SpOutputCollector;
+import org.apache.streampipes.wrapper.standalone.ProcessorParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataProcessor;
+
+public class FieldHasherProcessor extends StreamPipesDataProcessor {
+
+  private static final String HASH_PROPERTIES = "property-mapping";
+  private static final String HASH_ALGORITHM = "hash-algorithm";
+
+  private String propertyName;
+  private HashAlgorithm hashAlgorithm;
+
+  @Override
+  public DataProcessorDescription declareModel() {
+    return ProcessingElementBuilder.create("org.apache.streampipes.processors.transformation.jvm.fieldhasher")
+      .withLocales(Locales.EN)
+      .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+      .requiredStream(StreamRequirementsBuilder
+        .create()
+        .requiredPropertyWithUnaryMapping(EpRequirements.stringReq(), Labels.withId
+          (HASH_PROPERTIES), PropertyScope.NONE)
+        .build())
+      .requiredSingleValueSelection(Labels.withId(HASH_ALGORITHM),
+        Options.from("SHA1", "SHA2", "MD5"))
+      .outputStrategy(OutputStrategies.keep())
+      .build();
+  }
+
+  @Override
+  public void onInvocation(ProcessorParams parameters,
+                           SpOutputCollector spOutputCollector,
+                           EventProcessorRuntimeContext runtimeContext) throws SpRuntimeException {
+    var extractor = parameters.extractor();
+    this.propertyName = extractor.mappingPropertyValue(HASH_PROPERTIES);
+
+    this.hashAlgorithm = HashAlgorithmType.valueOf(extractor.selectedSingleValue(HASH_ALGORITHM, String.class)).hashAlgorithm();
+  }
+
+  @Override
+  public void onEvent(Event in, SpOutputCollector out) throws SpRuntimeException {
+    in.updateFieldBySelector(propertyName,
+      hashAlgorithm.toHashValue(in.getFieldBySelector(propertyName).getAsPrimitive().getAsString()));
+    out.collect(in);
+  }
+
+  @Override
+  public void onDetach() throws SpRuntimeException {
+
+  }
+}
diff --git a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/Operation.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/HashAlgorithm.java
similarity index 81%
copy from streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/Operation.java
copy to streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/HashAlgorithm.java
index e9cd593..5ee1162 100644
--- a/streampipes-extensions/streampipes-processors-enricher-flink/src/main/java/org/apache/streampipes/processors/enricher/flink/processor/math/operation/Operation.java
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/HashAlgorithm.java
@@ -16,11 +16,11 @@
  *
  */
 
-package org.apache.streampipes.processors.enricher.flink.processor.math.operation;
+package org.apache.streampipes.processors.transformation.jvm.processor.hasher.algorithm;
 
 import java.io.Serializable;
 
-public interface Operation extends Serializable {
+public interface HashAlgorithm extends Serializable {
 
-    Double operate(Double valLeft, Double valRight);
+	String toHashValue(Object value);
 }
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/HashAlgorithmType.java
similarity index 65%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/HashAlgorithmType.java
index 58ba04b..943aa40 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/HashAlgorithmType.java
@@ -16,3 +16,18 @@
  *
  */
 
+package org.apache.streampipes.processors.transformation.jvm.processor.hasher.algorithm;
+
+public enum HashAlgorithmType {
+	MD5(new Md5HashAlgorithm()), SHA1(new Sha1HashAlgorithm()), SHA2(new Sha2HashAlgorithm());
+
+	private HashAlgorithm hashAlgorithm;
+	
+	HashAlgorithmType(HashAlgorithm hashAlgorithm) {
+		this.hashAlgorithm = hashAlgorithm;
+	}
+	
+	public HashAlgorithm hashAlgorithm() {
+		return hashAlgorithm;
+	}
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Md5HashAlgorithm.java
similarity index 68%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Md5HashAlgorithm.java
index 58ba04b..96accec 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Md5HashAlgorithm.java
@@ -16,3 +16,17 @@
  *
  */
 
+package org.apache.streampipes.processors.transformation.jvm.processor.hasher.algorithm;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+public class Md5HashAlgorithm implements HashAlgorithm {
+
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	public String toHashValue(Object value) {
+		return DigestUtils.md5Hex(String.valueOf(value));
+	}
+
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Sha1HashAlgorithm.java
similarity index 68%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Sha1HashAlgorithm.java
index 58ba04b..2eb3997 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Sha1HashAlgorithm.java
@@ -16,3 +16,17 @@
  *
  */
 
+package org.apache.streampipes.processors.transformation.jvm.processor.hasher.algorithm;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+public class Sha1HashAlgorithm implements HashAlgorithm {
+
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	public String toHashValue(Object value) {
+		return DigestUtils.shaHex(String.valueOf(value));
+	}
+
+}
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Sha2HashAlgorithm.java
similarity index 68%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Sha2HashAlgorithm.java
index a375af7..7cfef6e 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/hasher/algorithm/Sha2HashAlgorithm.java
@@ -16,7 +16,17 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
-}
+package org.apache.streampipes.processors.transformation.jvm.processor.hasher.algorithm;
 
+import org.apache.commons.codec.digest.DigestUtils;
+
+public class Sha2HashAlgorithm implements HashAlgorithm {
+
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	public String toHashValue(Object value) {
+		return DigestUtils.sha256Hex(String.valueOf(value));
+	}
+
+}
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/mapper/FieldMapperProcessor.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/mapper/FieldMapperProcessor.java
new file mode 100644
index 0000000..48c49c4
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/mapper/FieldMapperProcessor.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.processors.transformation.jvm.processor.mapper;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.container.api.ResolvesContainerProvidedOutputStrategy;
+import org.apache.streampipes.model.graph.DataProcessorDescription;
+import org.apache.streampipes.model.graph.DataProcessorInvocation;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.model.schema.EventSchema;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.processors.transformation.jvm.processor.hasher.algorithm.HashAlgorithmType;
+import org.apache.streampipes.sdk.builder.PrimitivePropertyBuilder;
+import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor;
+import org.apache.streampipes.sdk.helpers.EpRequirements;
+import org.apache.streampipes.sdk.helpers.Labels;
+import org.apache.streampipes.sdk.helpers.Locales;
+import org.apache.streampipes.sdk.helpers.OutputStrategies;
+import org.apache.streampipes.sdk.utils.Assets;
+import org.apache.streampipes.sdk.utils.Datatypes;
+import org.apache.streampipes.wrapper.context.EventProcessorRuntimeContext;
+import org.apache.streampipes.wrapper.routing.SpOutputCollector;
+import org.apache.streampipes.wrapper.standalone.ProcessorParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataProcessor;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class FieldMapperProcessor extends StreamPipesDataProcessor implements ResolvesContainerProvidedOutputStrategy<DataProcessorInvocation, ProcessingElementParameterExtractor> {
+
+  private static final String REPLACE_PROPERTIES = "replaceProperties";
+  private static final String FIELD_NAME = "fieldName";
+
+  private List<String> replacePropertyNames;
+  private String newFieldName;
+
+  @Override
+  public DataProcessorDescription declareModel() {
+    return ProcessingElementBuilder.create("org.apache.streampipes.processors.transformation.jvm.field-mapper")
+      .withLocales(Locales.EN)
+      .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+      .requiredStream(StreamRequirementsBuilder
+        .create()
+        .requiredPropertyWithNaryMapping(EpRequirements.anyProperty(), Labels.withId
+          (REPLACE_PROPERTIES), PropertyScope.NONE)
+        .build())
+      .requiredTextParameter(Labels.withId(FIELD_NAME))
+      .outputStrategy(OutputStrategies.customTransformation())
+      .build();
+  }
+
+  @Override
+  public void onInvocation(ProcessorParams parameters,
+                           SpOutputCollector spOutputCollector,
+                           EventProcessorRuntimeContext runtimeContext) throws SpRuntimeException {
+    var extractor = parameters.extractor();
+    this.replacePropertyNames = extractor.mappingPropertyValues(REPLACE_PROPERTIES);
+    this.newFieldName = extractor.singleValueParameter(FIELD_NAME, String.class);
+  }
+
+  @Override
+  public void onEvent(Event in, SpOutputCollector out) throws SpRuntimeException {
+    Event event = new Event();
+    StringBuilder hashValue = new StringBuilder();
+    List<String> keys = in.getFields().keySet().stream().sorted().collect(Collectors.toList());
+    for (String key : keys) {
+      if (replacePropertyNames.stream().noneMatch(r -> r.equals(key))) {
+        event.addField(in.getFieldBySelector(key));
+      } else {
+        hashValue.append(in.getFieldBySelector((key)).getAsPrimitive().getAsString());
+      }
+    }
+
+    event.addField(newFieldName, HashAlgorithmType.MD5.hashAlgorithm().toHashValue(hashValue
+      .toString
+        ()));
+    out.collect(event);
+  }
+
+  @Override
+  public void onDetach() throws SpRuntimeException {
+
+  }
+
+  @Override
+  public EventSchema resolveOutputStrategy(DataProcessorInvocation processingElement,
+                                           ProcessingElementParameterExtractor extractor) throws SpRuntimeException {
+    List<String> replacePropertyNames = extractor.mappingPropertyValues(REPLACE_PROPERTIES);
+    String newFieldName = extractor.singleValueParameter(FIELD_NAME, String.class);
+
+    List<EventProperty> outProperties = extractor.getNoneInputStreamEventPropertySubset(replacePropertyNames);
+
+    EventPropertyPrimitive newProperty = PrimitivePropertyBuilder.create(Datatypes.String, newFieldName).build();
+    outProperties.add(newProperty);
+    return new EventSchema(outProperties);
+  }
+}
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/measurementconverter/MeasurementUnitConverterProcessor.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/measurementconverter/MeasurementUnitConverterProcessor.java
new file mode 100644
index 0000000..7090b68
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/measurementconverter/MeasurementUnitConverterProcessor.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.processors.transformation.jvm.processor.measurementconverter;
+
+import com.github.jqudt.Quantity;
+import com.github.jqudt.Unit;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.container.api.ResolvesContainerProvidedOptions;
+import org.apache.streampipes.model.graph.DataProcessorDescription;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.model.staticproperty.Option;
+import org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty;
+import org.apache.streampipes.sdk.builder.ProcessingElementBuilder;
+import org.apache.streampipes.sdk.builder.PropertyRequirementsBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.extractor.StaticPropertyExtractor;
+import org.apache.streampipes.sdk.helpers.Labels;
+import org.apache.streampipes.sdk.helpers.Locales;
+import org.apache.streampipes.sdk.helpers.OutputStrategies;
+import org.apache.streampipes.sdk.helpers.TransformOperations;
+import org.apache.streampipes.sdk.utils.Assets;
+import org.apache.streampipes.units.UnitProvider;
+import org.apache.streampipes.wrapper.context.EventProcessorRuntimeContext;
+import org.apache.streampipes.wrapper.routing.SpOutputCollector;
+import org.apache.streampipes.wrapper.standalone.ProcessorParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataProcessor;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class MeasurementUnitConverterProcessor extends StreamPipesDataProcessor implements ResolvesContainerProvidedOptions {
+
+  private static final String CONVERT_PROPERTY = "convert-property";
+  private static final String OUTPUT_UNIT = "output-unit";
+
+  private Unit inputUnit;
+  private Unit outputUnit;
+
+  private String convertProperty;
+
+  @Override
+  public DataProcessorDescription declareModel() {
+    return ProcessingElementBuilder.create("org.apache.streampipes.processors.transformation.jvm.measurementunitconverter")
+      .withLocales(Locales.EN)
+      .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+      .requiredStream(StreamRequirementsBuilder
+        .create()
+        .requiredPropertyWithUnaryMapping(PropertyRequirementsBuilder
+            .create()
+            .measurementUnitPresence()
+            .build(),
+          Labels.withId(CONVERT_PROPERTY),
+          PropertyScope.MEASUREMENT_PROPERTY)
+        .build())
+      .requiredSingleValueSelectionFromContainer(Labels.withId(OUTPUT_UNIT))
+      .outputStrategy(OutputStrategies.transform(TransformOperations
+        .dynamicMeasurementUnitTransformation(CONVERT_PROPERTY, OUTPUT_UNIT)))
+      .build();
+  }
+
+  @Override
+  public void onInvocation(ProcessorParams parameters, SpOutputCollector spOutputCollector, EventProcessorRuntimeContext runtimeContext) throws SpRuntimeException {
+    var extractor = parameters.extractor();
+
+    this.convertProperty = extractor.mappingPropertyValue(CONVERT_PROPERTY);
+    String runtimeName = extractor.getEventPropertyBySelector(this.convertProperty).getRuntimeName();
+    String inputUnitId = extractor.measurementUnit(runtimeName, 0);
+    String outputUnitId = parameters.getGraph().getStaticProperties().stream().filter(sp -> sp
+        .getInternalName().equals(OUTPUT_UNIT))
+      .map(sp ->
+        (RuntimeResolvableOneOfStaticProperty) sp)
+      .findFirst()
+      .get().getOptions()
+      .stream
+        ().filter(Option::isSelected).map(Option::getInternalName).findFirst().get();
+
+    this.inputUnit = UnitProvider.INSTANCE.getUnit(inputUnitId);
+    this.outputUnit = UnitProvider.INSTANCE.getUnit(outputUnitId);
+  }
+
+  @Override
+  public void onEvent(Event in, SpOutputCollector out) throws SpRuntimeException {
+    double value = in.getFieldBySelector(convertProperty).getAsPrimitive().getAsDouble();
+
+    // transform old value to new unit
+    Quantity obs = new Quantity(value, inputUnit);
+    try {
+      Double newValue = obs.convertTo(outputUnit).getValue();
+      in.updateFieldBySelector(convertProperty, newValue);
+      out.collect(in);
+    } catch (IllegalAccessException e) {
+      throw new SpRuntimeException("Could not convert measurement", e);
+    }
+  }
+
+  @Override
+  public void onDetach() throws SpRuntimeException {
+
+  }
+
+  @Override
+  public List<Option> resolveOptions(String staticPropertyInternalName, StaticPropertyExtractor parameterExtractor) {
+    try {
+      String selector = parameterExtractor.mappingPropertyValue(CONVERT_PROPERTY);
+      EventProperty linkedEventProperty = parameterExtractor.getEventPropertyBySelector(selector);
+      if (linkedEventProperty instanceof EventPropertyPrimitive && ((EventPropertyPrimitive) linkedEventProperty)
+        .getMeasurementUnit() != null) {
+        Unit measurementUnit = UnitProvider.INSTANCE.getUnit(((EventPropertyPrimitive) linkedEventProperty)
+          .getMeasurementUnit().toString());
+        URI type = measurementUnit.getType();
+        List<Unit> availableUnits = UnitProvider.INSTANCE.getUnitsByType(type);
+        return availableUnits
+          .stream()
+          .filter(unit -> !(unit.getResource().toString().equals(measurementUnit.getResource().toString())))
+          .map(unit -> new Option(unit.getLabel(), unit.getResource().toString()))
+          .collect(Collectors.toList());
+      } else {
+        return new ArrayList<>();
+      }
+    } catch (SpRuntimeException e) {
+      e.printStackTrace();
+      return new ArrayList<>();
+    }
+  }
+}
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/documentation.md b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/documentation.md
new file mode 100644
index 0000000..8babeef
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/documentation.md
@@ -0,0 +1,63 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+## Field Mapper
+
+<p align="center"> 
+    <img src="icon.png" width="150px;" class="pe-image-documentation"/>
+</p>
+
+***
+
+## Description
+
+Replaces one or more fields with a new field and computes a hash value of these fields
+
+***
+
+## Configuration
+
+* Fields: Fields that will be mapped into a property
+* Name of the new field
+
+***
+
+## Example
+Merge two fields into a hash value
+### Input  event
+```
+{
+  "timestamp":1586380104915,
+  "mass_flow":4.3167,
+  "temperature":40.05,
+  "sensorId":"flowrate01"
+}
+```
+
+### Configuration
+* Fields: mass_flow, temperature
+* Name of new field: demo
+
+### Output event 
+```
+{
+  "timestamp":1586380104915,
+  "sensorId":"flowrate01"
+  "demo":"8ae11f5c83610104408d485b73120832",
+}
+```
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/icon.png b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/icon.png
new file mode 100644
index 0000000..2eafc5f
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/icon.png
Binary files differ
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/strings.en b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/strings.en
new file mode 100644
index 0000000..cf570b5
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.field-mapper/strings.en
@@ -0,0 +1,8 @@
+org.apache.streampipes.processors.transformation.jvm.field-mapper.title=Field Mapper
+org.apache.streampipes.processors.transformation.jvm.field-mapper.description=Replaces one or more field with a new field and computes a hash value of these fields
+
+replaceProperties.title=Fields
+replaceProperties.description=The fields to replace
+
+fieldName.title=New Field Name
+fieldName.description=The name of the new field
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/documentation.md b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/documentation.md
new file mode 100644
index 0000000..4049b6d
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/documentation.md
@@ -0,0 +1,48 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+## Field Hasher
+
+<p align="center"> 
+    <img src="icon.png" width="150px;" class="pe-image-documentation"/>
+</p>
+
+***
+
+## Description
+
+The Field Hasher uses an algorithm to encode values in a field. The Field Hasher can use MD5, SHA1 or SHA2 to hash field values.
+
+***
+
+## Required input
+This processor requires at least one field of type string.
+
+***
+
+## Configuration
+
+### Field
+Specifies the string field that will be encoded.
+
+### Hash Algorithm
+Specifies the algorithm used to encode the string field. The following algorithms
+are available: SHA2, MD5 or SHA1.
+
+## Output
+The encoded string field.
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/icon.png b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/icon.png
new file mode 100644
index 0000000..f9fa3a2
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/icon.png
Binary files differ
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/strings.en b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/strings.en
new file mode 100644
index 0000000..561f434
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.fieldhasher/strings.en
@@ -0,0 +1,8 @@
+org.apache.streampipes.processors.transformation.jvm.fieldhasher.title=Field Hasher
+org.apache.streampipes.processors.transformation.jvm.fieldhasher.description=Hashes the value of a field using various hash functions.
+
+property-mapping.title=Field
+property-mapping.description=The field the hash function should be applied on
+
+hash-algorithm.title=Hash Algorithm
+hash-algorithm.description=The hash algorithm that should be used.
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.html b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/documentation.md
similarity index 70%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.html
rename to streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/documentation.md
index 92c744b..f9b8e88 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.html
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/documentation.md
@@ -16,6 +16,32 @@
   ~
   -->
 
-<sp-edit-data-type
-        [cachedProperty]= "cachedProperty.eventProperty">
-</sp-edit-data-type>
+## Measurement Unit Converter
+
+<p align="center"> 
+    <img src="icon.png" width="150px;" class="pe-image-documentation"/>
+</p>
+
+***
+
+## Description
+
+Converts a unit of measurement to another one.
+
+***
+
+## Required input
+
+
+***
+
+## Configuration
+
+Describe the configuration parameters here
+
+### 1st parameter
+
+
+### 2nd parameter
+
+## Output
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/icon.png b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/icon.png
new file mode 100644
index 0000000..ebe9f3a
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/icon.png
Binary files differ
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/strings.en b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/strings.en
new file mode 100644
index 0000000..754f04b
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/resources/org.apache.streampipes.processors.transformation.jvm.measurementunitconverter/strings.en
@@ -0,0 +1,8 @@
+org.apache.streampipes.processors.transformation.jvm.measurementunitconverter.title=Measurement Unit Converter
+org.apache.streampipes.processors.transformation.jvm.measurementunitconverter.description=Converts a unit of measurement to another one
+
+convert-property.title=Field
+convert-property.description=The field to convert
+
+output-unit.title=Output Unit
+output-unit.description=The output type unit of measurement
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/Dockerfile b/streampipes-extensions/streampipes-sinks-brokers-jvm/Dockerfile
deleted file mode 100644
index 630bd7b..0000000
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-sinks-brokers-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-sinks-brokers-jvm/aarch64.Dockerfile
deleted file mode 100644
index 3fc0649..0000000
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-sinks-brokers-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-sinks-brokers-jvm/arm.Dockerfile
deleted file mode 100644
index 9ca1b46..0000000
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-sinks-brokers-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/development/env b/streampipes-extensions/streampipes-sinks-brokers-jvm/development/env
deleted file mode 100644
index f191f5a..0000000
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/development/env
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=7005
-SP_HOST=host.docker.internal
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/pom.xml b/streampipes-extensions/streampipes-sinks-brokers-jvm/pom.xml
index 1d3d526..9b8ef3e 100644
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-sinks-brokers-jvm/pom.xml
@@ -21,32 +21,28 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-sinks-brokers-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-elements-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -106,37 +102,12 @@
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-sinks-brokers-jvm</finalName>
-    </build>
 </project>
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/BrokersJvmInit.java b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/BrokersJvmInit.java
index 97dad40..9910a94 100644
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/BrokersJvmInit.java
+++ b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/BrokersJvmInit.java
@@ -33,7 +33,7 @@
 import org.apache.streampipes.sinks.brokers.jvm.kafka.KafkaController;
 import org.apache.streampipes.sinks.brokers.jvm.mqtt.MqttPublisherSink;
 import org.apache.streampipes.sinks.brokers.jvm.nats.NatsController;
-import org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarController;
+import org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarPublisherSink;
 import org.apache.streampipes.sinks.brokers.jvm.rabbitmq.RabbitMqController;
 import org.apache.streampipes.sinks.brokers.jvm.rest.RestController;
 import org.apache.streampipes.sinks.brokers.jvm.websocket.WebsocketServerSink;
@@ -58,7 +58,7 @@
                     new RabbitMqController(),
                     new MqttPublisherSink(),
                     new WebsocketServerSink(),
-                    new PulsarController(),
+                    new PulsarPublisherSink(),
                     new NatsController())
             .registerMessagingFormats(
                     new JsonDataFormatFactory(),
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/Pulsar.java b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/Pulsar.java
deleted file mode 100644
index c51ce93..0000000
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/Pulsar.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.streampipes.sinks.brokers.jvm.pulsar;
-
-import org.apache.pulsar.client.api.Producer;
-import org.apache.pulsar.client.api.PulsarClient;
-import org.apache.pulsar.client.api.PulsarClientException;
-import org.apache.streampipes.commons.exceptions.SpRuntimeException;
-import org.apache.streampipes.dataformat.SpDataFormatDefinition;
-import org.apache.streampipes.dataformat.json.JsonDataFormatDefinition;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.wrapper.context.EventSinkRuntimeContext;
-import org.apache.streampipes.wrapper.runtime.EventSink;
-
-import java.util.Map;
-
-public class Pulsar implements EventSink<PulsarParameters> {
-
-  private static final String PulsarScheme = "pulsar://";
-  private static final String Colon = ":";
-
-  private Producer<byte[]> producer;
-  private PulsarClient pulsarClient;
-  private SpDataFormatDefinition spDataFormatDefinition;
-
-  public Pulsar() {
-    this.spDataFormatDefinition = new JsonDataFormatDefinition();
-  }
-
-  @Override
-  public void onInvocation(PulsarParameters params,
-                           EventSinkRuntimeContext eventSinkRuntimeContext) throws SpRuntimeException {
-    try {
-     this.pulsarClient = PulsarClient.builder()
-              .serviceUrl(makePulsarUrl(params.getPulsarHost(), params.getPulsarPort()))
-              .build();
-
-      this.producer = this.pulsarClient.newProducer()
-              .topic(params.getTopic())
-              .create();
-    } catch (PulsarClientException e) {
-      throw new SpRuntimeException(e);
-    }
-  }
-
-  @Override
-  public void onEvent(Event event) throws SpRuntimeException {
-    Map<String, Object> rawMap = event.getRaw();
-    byte[] jsonMessage = this.spDataFormatDefinition.fromMap(rawMap);
-
-    try {
-      this.producer.send(jsonMessage);
-    } catch (PulsarClientException e) {
-      throw new SpRuntimeException(e);
-    }
-  }
-
-  @Override
-  public void onDetach() throws SpRuntimeException {
-    try {
-      this.pulsarClient.close();
-    } catch (PulsarClientException e) {
-      throw new SpRuntimeException(e);
-    }
-  }
-
-  private String makePulsarUrl(String hostname, Integer port) {
-    return PulsarScheme + hostname + Colon + port;
-  }
-}
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarController.java b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarController.java
deleted file mode 100644
index b79458c..0000000
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarController.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.streampipes.sinks.brokers.jvm.pulsar;
-
-import org.apache.streampipes.model.DataSinkType;
-import org.apache.streampipes.model.graph.DataSinkDescription;
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.sdk.builder.DataSinkBuilder;
-import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
-import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor;
-import org.apache.streampipes.sdk.helpers.EpRequirements;
-import org.apache.streampipes.sdk.helpers.Labels;
-import org.apache.streampipes.sdk.helpers.Locales;
-import org.apache.streampipes.sdk.utils.Assets;
-import org.apache.streampipes.wrapper.standalone.ConfiguredEventSink;
-import org.apache.streampipes.wrapper.standalone.declarer.StandaloneEventSinkDeclarer;
-
-public class PulsarController extends StandaloneEventSinkDeclarer<PulsarParameters> {
-
-  private static final String TOPIC_KEY = "topic";
-  private static final String PULSAR_HOST_KEY = "pulsar-host";
-  private static final String PULSAR_PORT_KEY = "pulsar-port";
-
-  @Override
-  public DataSinkDescription declareModel() {
-    return DataSinkBuilder.create("org.apache.streampipes.sinks.brokers.jvm.pulsar")
-            .category(DataSinkType.MESSAGING)
-            .withLocales(Locales.EN)
-            .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-            .requiredStream(StreamRequirementsBuilder
-                    .create()
-                    .requiredProperty(EpRequirements.anyProperty())
-                    .build())
-            .requiredTextParameter(Labels.withId(PULSAR_HOST_KEY))
-            .requiredIntegerParameter(Labels.withId(PULSAR_PORT_KEY), 6650)
-            .requiredTextParameter(Labels.withId(TOPIC_KEY))
-            .build();
-  }
-
-  @Override
-  public ConfiguredEventSink<PulsarParameters> onInvocation(DataSinkInvocation graph,
-                                                          DataSinkParameterExtractor extractor) {
-    String pulsarHost = extractor.singleValueParameter(PULSAR_HOST_KEY, String.class);
-    Integer pulsarPort = extractor.singleValueParameter(PULSAR_PORT_KEY, Integer.class);
-    String topic = extractor.singleValueParameter(TOPIC_KEY, String.class);
-
-    PulsarParameters params = new PulsarParameters(graph, pulsarHost, pulsarPort, topic);
-
-    return new ConfiguredEventSink<>(params, Pulsar::new);
-  }
-
-
-}
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarParameters.java b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarParameters.java
index 82351ee..0accba0 100644
--- a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarParameters.java
+++ b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarParameters.java
@@ -17,21 +17,22 @@
  */
 package org.apache.streampipes.sinks.brokers.jvm.pulsar;
 
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.wrapper.params.binding.EventSinkBindingParams;
+import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor;
+import org.apache.streampipes.wrapper.standalone.SinkParams;
 
-public class PulsarParameters extends EventSinkBindingParams {
+import static org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarPublisherSink.*;
 
+public class PulsarParameters {
   private String pulsarHost;
   private Integer pulsarPort;
   private String topic;
 
-  public PulsarParameters(DataSinkInvocation graph, String pulsarHost, Integer pulsarPort,
-                          String topic) {
-    super(graph);
-    this.pulsarHost = pulsarHost;
-    this.pulsarPort = pulsarPort;
-    this.topic = topic;
+  public PulsarParameters(SinkParams parameters) {
+    DataSinkParameterExtractor extractor = parameters.extractor();
+
+    this.pulsarHost = extractor.singleValueParameter(PULSAR_HOST_KEY, String.class);
+    this.pulsarPort = extractor.singleValueParameter(PULSAR_PORT_KEY, Integer.class);
+    this.topic = extractor.singleValueParameter(TOPIC_KEY, String.class);
   }
 
   public String getPulsarHost() {
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarPublisherSink.java b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarPublisherSink.java
new file mode 100644
index 0000000..0eadc54
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/main/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/PulsarPublisherSink.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.sinks.brokers.jvm.pulsar;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.util.Map;
+import org.apache.pulsar.client.api.ClientBuilder;
+import org.apache.pulsar.client.api.Producer;
+import org.apache.pulsar.client.api.PulsarClient;
+import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.dataformat.SpDataFormatDefinition;
+import org.apache.streampipes.dataformat.json.JsonDataFormatDefinition;
+import org.apache.streampipes.model.DataSinkType;
+import org.apache.streampipes.model.graph.DataSinkDescription;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.sdk.builder.DataSinkBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.helpers.EpRequirements;
+import org.apache.streampipes.sdk.helpers.Labels;
+import org.apache.streampipes.sdk.helpers.Locales;
+import org.apache.streampipes.sdk.utils.Assets;
+import org.apache.streampipes.wrapper.context.EventSinkRuntimeContext;
+import org.apache.streampipes.wrapper.standalone.SinkParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataSink;
+
+public class PulsarPublisherSink extends StreamPipesDataSink {
+
+    public static final String TOPIC_KEY = "topic";
+    public static final String PULSAR_HOST_KEY = "pulsar-host";
+    public static final String PULSAR_PORT_KEY = "pulsar-port";
+    private static final String PulsarScheme = "pulsar://";
+    private static final String Colon = ":";
+    private final ClientBuilder clientBuilder;
+    private Producer<byte[]> producer;
+    private PulsarClient pulsarClient;
+    private SpDataFormatDefinition spDataFormatDefinition;
+    private PulsarParameters params;
+
+    public PulsarPublisherSink() {
+        this.clientBuilder = PulsarClient.builder();
+    }
+
+    @VisibleForTesting
+    public PulsarPublisherSink(ClientBuilder pulsarClientBuilder) {
+        this.clientBuilder = pulsarClientBuilder;
+    }
+
+    @Override
+    public DataSinkDescription declareModel() {
+        return DataSinkBuilder.create("org.apache.streampipes.sinks.brokers.jvm.pulsar")
+                .category(DataSinkType.MESSAGING)
+                .withLocales(Locales.EN)
+                .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+                .requiredStream(StreamRequirementsBuilder
+                        .create()
+                        .requiredProperty(EpRequirements.anyProperty())
+                        .build())
+                .requiredTextParameter(Labels.withId(PULSAR_HOST_KEY))
+                .requiredIntegerParameter(Labels.withId(PULSAR_PORT_KEY), 6650)
+                .requiredTextParameter(Labels.withId(TOPIC_KEY))
+                .build();
+    }
+
+    @Override
+    public void onInvocation(SinkParams parameters, EventSinkRuntimeContext runtimeContext) throws SpRuntimeException {
+        params = new PulsarParameters(parameters);
+
+        this.spDataFormatDefinition = new JsonDataFormatDefinition();
+        try {
+            this.pulsarClient = clientBuilder.serviceUrl(makePulsarUrl(params.getPulsarHost(), params.getPulsarPort()))
+                    .build();
+
+            this.producer = this.pulsarClient.newProducer()
+                    .topic(params.getTopic())
+                    .create();
+        } catch (PulsarClientException e) {
+            throw new SpRuntimeException(e);
+        }
+    }
+
+    @Override
+    public void onEvent(Event event) throws SpRuntimeException {
+        Map<String, Object> rawMap = event.getRaw();
+        byte[] jsonMessage = this.spDataFormatDefinition.fromMap(rawMap);
+
+        try {
+            this.producer.send(jsonMessage);
+        } catch (PulsarClientException e) {
+            throw new SpRuntimeException(e);
+        }
+    }
+
+    @Override
+    public void onDetach() throws SpRuntimeException {
+        try {
+            this.pulsarClient.close();
+        } catch (PulsarClientException e) {
+            throw new SpRuntimeException(e);
+        }
+    }
+
+    private String makePulsarUrl(String hostname, Integer port) {
+        return PulsarScheme + hostname + Colon + port;
+    }
+}
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/test/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/TestPulsarParameters.java b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/test/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/TestPulsarParameters.java
new file mode 100644
index 0000000..aaf4fd2
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/test/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/TestPulsarParameters.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.sinks.brokers.jvm.pulsar;
+
+import static org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarPublisherSink.PULSAR_HOST_KEY;
+import static org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarPublisherSink.PULSAR_PORT_KEY;
+import static org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarPublisherSink.TOPIC_KEY;
+import static org.mockito.Mockito.mock;
+import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor;
+import org.apache.streampipes.wrapper.standalone.SinkParams;
+import org.junit.Assert;
+import org.mockito.Mockito;
+import org.junit.Test;
+
+public class TestPulsarParameters {
+    @Test
+    public void testInitPulsarParameters() {
+        String pulsarHost = "localhost";
+        Integer pulsarPort = 6650;
+        String topic = "test";
+
+        SinkParams params = mock(SinkParams.class);
+        DataSinkParameterExtractor extractor = mock(DataSinkParameterExtractor.class);
+        Mockito.when(params.extractor()).thenReturn(extractor);
+        Mockito.when(extractor.singleValueParameter(PULSAR_HOST_KEY, String.class)).thenReturn(pulsarHost);
+        Mockito.when(extractor.singleValueParameter(PULSAR_PORT_KEY, Integer.class)).thenReturn(pulsarPort);
+        Mockito.when(extractor.singleValueParameter(TOPIC_KEY, String.class)).thenReturn(topic);
+
+        PulsarParameters pulsarParameters = new PulsarParameters(params);
+
+        Assert.assertEquals(pulsarHost, pulsarParameters.getPulsarHost());
+        Assert.assertEquals(pulsarPort, pulsarParameters.getPulsarPort());
+        Assert.assertEquals(topic, pulsarParameters.getTopic());
+    }
+}
diff --git a/streampipes-extensions/streampipes-sinks-brokers-jvm/src/test/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/TestPulsarPublisherSink.java b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/test/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/TestPulsarPublisherSink.java
new file mode 100644
index 0000000..5e15a13
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-brokers-jvm/src/test/java/org/apache/streampipes/sinks/brokers/jvm/pulsar/TestPulsarPublisherSink.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.sinks.brokers.jvm.pulsar;
+
+import static org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarPublisherSink.PULSAR_HOST_KEY;
+import static org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarPublisherSink.PULSAR_PORT_KEY;
+import static org.apache.streampipes.sinks.brokers.jvm.pulsar.PulsarPublisherSink.TOPIC_KEY;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.pulsar.client.api.ClientBuilder;
+import org.apache.pulsar.client.api.Producer;
+import org.apache.pulsar.client.api.ProducerBuilder;
+import org.apache.pulsar.client.api.PulsarClient;
+import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor;
+import org.apache.streampipes.wrapper.standalone.SinkParams;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestPulsarPublisherSink {
+    @Test
+    public void testSimpleEventSink() throws PulsarClientException {
+        String pulsarHost = "localhost";
+        Integer pulsarPort = 6650;
+        String topic = "test";
+
+        Map<String, Object> rawMap = new HashMap<>(2);
+
+        rawMap.put("key1", "value1");
+        rawMap.put("key2", "value2");
+
+        SinkParams params = mock(SinkParams.class);
+        DataSinkParameterExtractor extractor = mock(DataSinkParameterExtractor.class);
+        when(params.extractor()).thenReturn(extractor);
+        when(extractor.singleValueParameter(PULSAR_HOST_KEY, String.class)).thenReturn(pulsarHost);
+        when(extractor.singleValueParameter(PULSAR_PORT_KEY, Integer.class)).thenReturn(pulsarPort);
+        when(extractor.singleValueParameter(TOPIC_KEY, String.class)).thenReturn(topic);
+
+        ClientBuilder clientBuilder = mock(ClientBuilder.class);
+        PulsarClient pulsarClient = mock(PulsarClient.class);
+        ProducerBuilder<byte[]> producerBuilder = mock(ProducerBuilder.class);
+        Producer<byte[]> producer = mock(Producer.class);
+        when(clientBuilder.serviceUrl(anyString())).thenReturn(clientBuilder);
+        when(clientBuilder.build()).thenReturn(pulsarClient);
+        when(pulsarClient.newProducer()).thenReturn(producerBuilder);
+        when(producerBuilder.topic(topic)).thenReturn(producerBuilder);
+        when(producerBuilder.create()).thenReturn(producer);
+        when(producer.send(Mockito.any(byte[].class))).thenAnswer(data -> {
+            HashMap<String, String> map;
+            ObjectMapper mapper = new ObjectMapper();
+            String json = new String((byte[]) data.getArgument(0));
+            map = mapper.readValue(json, new TypeReference<>() {
+            });
+            Assert.assertEquals(map, rawMap);
+            return null;
+        });
+
+        PulsarPublisherSink pulsarPublisherSink = new PulsarPublisherSink(clientBuilder);
+
+        // Test invocation
+        pulsarPublisherSink.onInvocation(params, null);
+
+        verify(clientBuilder).serviceUrl(String.format("pulsar://%s:%d", pulsarHost, pulsarPort));
+
+        // Test publish event
+        Event event = mock(Event.class);
+        when(event.getRaw()).thenReturn(rawMap);
+
+        pulsarPublisherSink.onEvent(event);
+
+        verify(producer, times(1)).send(Mockito.any(byte[].class));
+    }
+}
diff --git a/streampipes-extensions/streampipes-sinks-databases-flink/Dockerfile b/streampipes-extensions/streampipes-sinks-databases-flink/Dockerfile
deleted file mode 100644
index 2402500..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-flink/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-sinks-databases-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-databases-flink/aarch64.Dockerfile b/streampipes-extensions/streampipes-sinks-databases-flink/aarch64.Dockerfile
deleted file mode 100644
index e62b5a4..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-flink/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-sinks-databases-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-databases-flink/arm.Dockerfile b/streampipes-extensions/streampipes-sinks-databases-flink/arm.Dockerfile
deleted file mode 100644
index 7b2be61..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-flink/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-sinks-databases-flink.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-databases-flink/development/env b/streampipes-extensions/streampipes-sinks-databases-flink/development/env
deleted file mode 100644
index c84aed9..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-flink/development/env
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=7010
-SP_HOST=host.docker.internal
-SP_DEBUG=true
-SP_FLINK_DEBUG=true
-SP_ELASTICSEARCH_HOST=localhost
diff --git a/streampipes-extensions/streampipes-sinks-databases-flink/pom.xml b/streampipes-extensions/streampipes-sinks-databases-flink/pom.xml
index 24e0d8c..f87c6d6 100644
--- a/streampipes-extensions/streampipes-sinks-databases-flink/pom.xml
+++ b/streampipes-extensions/streampipes-sinks-databases-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -36,12 +36,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-flink</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/Dockerfile b/streampipes-extensions/streampipes-sinks-databases-jvm/Dockerfile
deleted file mode 100644
index 2ab40ee..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-sinks-databases-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-sinks-databases-jvm/aarch64.Dockerfile
deleted file mode 100644
index 3da3590..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-sinks-databases-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-sinks-databases-jvm/arm.Dockerfile
deleted file mode 100644
index 200b0fe..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-sinks-databases-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/development/env b/streampipes-extensions/streampipes-sinks-databases-jvm/development/env
deleted file mode 100644
index 6a41c19..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/development/env
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=7015
-SP_HOST=host.docker.internal
-SP_DEBUG=true
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/pom.xml b/streampipes-extensions/streampipes-sinks-databases-jvm/pom.xml
index 4aa929b..2f4e1e4 100644
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-sinks-databases-jvm/pom.xml
@@ -21,27 +21,23 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-sinks-databases-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -79,10 +75,6 @@
             <groupId>redis.clients</groupId>
             <artifactId>jedis</artifactId>
         </dependency>
-        <dependency>
-            <groupId>mysql</groupId>
-            <artifactId>mysql-connector-java</artifactId>
-        </dependency>
 
         <!-- 3rd party dependencies to avoid convergence errors -->
         <dependency>
@@ -120,39 +112,4 @@
             <artifactId>jcl-over-slf4j</artifactId>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                        <configuration>
-                            <mainClass>org.apache.streampipes.sinks.databases.jvm.DatabasesJvmInit</mainClass>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-sinks-databases-jvm</finalName>
-    </build>
 </project>
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/DatabasesJvmInit.java b/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/DatabasesJvmInit.java
index 528b538..cb1a38a 100644
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/DatabasesJvmInit.java
+++ b/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/DatabasesJvmInit.java
@@ -32,7 +32,6 @@
 import org.apache.streampipes.sinks.databases.jvm.ditto.DittoController;
 import org.apache.streampipes.sinks.databases.jvm.influxdb.InfluxDbController;
 import org.apache.streampipes.sinks.databases.jvm.iotdb.IotDbController;
-import org.apache.streampipes.sinks.databases.jvm.mysql.MysqlController;
 import org.apache.streampipes.sinks.databases.jvm.opcua.UpcUaController;
 import org.apache.streampipes.sinks.databases.jvm.postgresql.PostgreSqlController;
 import org.apache.streampipes.sinks.databases.jvm.redis.RedisController;
@@ -56,8 +55,7 @@
                     new PostgreSqlController(),
                     new IotDbController(),
                     new DittoController(),
-                    new RedisController(),
-                    new MysqlController())
+                    new RedisController())
             .registerMessagingFormats(
                     new JsonDataFormatFactory(),
                     new CborDataFormatFactory(),
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/Mysql.java b/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/Mysql.java
deleted file mode 100644
index 510d1fd..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/Mysql.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.databases.jvm.mysql;
-
-import org.apache.streampipes.commons.exceptions.SpRuntimeException;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.logging.api.Logger;
-import org.apache.streampipes.sinks.databases.jvm.jdbcclient.JdbcClient;
-import org.apache.streampipes.sinks.databases.jvm.jdbcclient.model.SupportedDbEngines;
-import org.apache.streampipes.wrapper.context.EventSinkRuntimeContext;
-import org.apache.streampipes.wrapper.runtime.EventSink;
-
-
-public class Mysql extends JdbcClient implements EventSink<MysqlParameters> {
-
-    private MysqlParameters params;
-    private final SupportedDbEngines dbEngine = SupportedDbEngines.MY_SQL;
-
-    @Override
-    public void onInvocation(MysqlParameters params, EventSinkRuntimeContext runtimeContext) throws SpRuntimeException {
-
-        this.params = params;
-        Logger LOG = params.getGraph().getLogger(Mysql.class);
-
-        initializeJdbc(
-                params.getGraph().getInputStreams().get(0).getEventSchema(),
-                params,
-                dbEngine,
-                LOG);
-    }
-
-
-    @Override
-    public void onEvent(Event inputEvent) {
-        try {
-            save(inputEvent);
-        } catch (SpRuntimeException e) {
-            e.printStackTrace();
-        }
-    }
-
-
-    @Override
-    public void onDetach() throws SpRuntimeException {
-        closeAll();
-    }
-
-
-    @Override
-    protected void ensureDatabaseExists(String databaseName) throws SpRuntimeException {
-
-        String createStatement = "CREATE DATABASE IF NOT EXISTS ";
-
-        ensureDatabaseExists(createStatement, databaseName);
-
-    }
-
-    @Override
-    protected void extractTableInformation() throws SpRuntimeException {
-
-        String query = "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE FROM "
-                + "INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ? ORDER BY "
-                + "ORDINAL_POSITION ASC;";
-
-        String[] queryParameter = new String[]{params.getDbTable(), params.getDbName()};
-
-        this.tableDescription.extractTableInformation(
-                this.statementHandler.preparedStatement, this.connection,
-                query, queryParameter);
-    }
-
-
-}
-
-
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/MysqlController.java b/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/MysqlController.java
deleted file mode 100644
index 927ac7d..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/MysqlController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.databases.jvm.mysql;
-
-import org.apache.streampipes.model.DataSinkType;
-import org.apache.streampipes.model.graph.DataSinkDescription;
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.sdk.builder.DataSinkBuilder;
-import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
-import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor;
-import org.apache.streampipes.sdk.helpers.EpRequirements;
-import org.apache.streampipes.sdk.helpers.Labels;
-import org.apache.streampipes.sdk.helpers.Locales;
-import org.apache.streampipes.sdk.utils.Assets;
-import org.apache.streampipes.wrapper.standalone.ConfiguredEventSink;
-import org.apache.streampipes.wrapper.standalone.declarer.StandaloneEventSinkDeclarer;
-
-public class MysqlController extends StandaloneEventSinkDeclarer<MysqlParameters> {
-
-    private static final String HOST_KEY = "host";
-    private static final String USER_KEY = "user";
-    private static final String PASSWORD_KEY = "password";
-    private static final String DB_KEY = "db";
-    private static final String TABLE_KEY = "table";
-    private static final String PORT_KEY = "port";
-
-    @Override
-    public DataSinkDescription declareModel() {
-        return DataSinkBuilder.create("org.apache.streampipes.sinks.databases.jvm.mysql")
-                .category(DataSinkType.DATABASE)
-                .withLocales(Locales.EN)
-                .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-                .requiredStream(StreamRequirementsBuilder
-                        .create()
-                        .requiredProperty(EpRequirements.anyProperty())
-                        .build())
-                .requiredTextParameter(Labels.withId(HOST_KEY), false, false)
-                .requiredIntegerParameter(Labels.withId(PORT_KEY), 3306)
-                .requiredTextParameter(Labels.withId(USER_KEY), false, false)
-                .requiredSecret(Labels.withId(PASSWORD_KEY))
-                .requiredTextParameter(Labels.withId(DB_KEY), false, false)
-                .requiredTextParameter(Labels.withId(TABLE_KEY), false, false)
-                .build();
-    }
-
-    @Override
-    public ConfiguredEventSink<MysqlParameters> onInvocation(DataSinkInvocation graph,
-                                                             DataSinkParameterExtractor extractor) {
-
-        String host = extractor.singleValueParameter(HOST_KEY, String.class);
-        String user = extractor.singleValueParameter(USER_KEY, String.class);
-        String password = extractor.secretValue(PASSWORD_KEY);
-        String db = extractor.singleValueParameter(DB_KEY, String.class);
-        String table = extractor.singleValueParameter(TABLE_KEY, String.class);
-        Integer port = extractor.singleValueParameter(PORT_KEY, Integer.class);
-
-        // SSL connection is not yet implemented for MySQL client
-        MysqlParameters params = new MysqlParameters(graph, host, user, password, db, table, port, false);
-        return new ConfiguredEventSink<>(params, Mysql::new);
-    }
-
-}
diff --git a/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/MysqlParameters.java b/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/MysqlParameters.java
deleted file mode 100644
index 40180ca..0000000
--- a/streampipes-extensions/streampipes-sinks-databases-jvm/src/main/java/org/apache/streampipes/sinks/databases/jvm/mysql/MysqlParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.databases.jvm.mysql;
-
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.sinks.databases.jvm.jdbcclient.model.JdbcConnectionParameters;
-
-public class MysqlParameters extends JdbcConnectionParameters {
-
-    public MysqlParameters(DataSinkInvocation graph, String mySqlHost, String mySqlUser, String mySqlPassword,
-                           String mySqlDb, String mySqlTable, Integer mySqlPort, boolean sslEnabled) {
-        super(
-                graph,
-                mySqlHost,
-                mySqlPort,
-                mySqlDb,
-                mySqlUser,
-                mySqlPassword,
-                mySqlTable,
-                sslEnabled,
-                null,
-                false
-        );
-    }
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-sinks-internal-jvm/aarch64.Dockerfile
deleted file mode 100644
index b1d2f6e..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-sinks-internal-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-sinks-internal-jvm/arm.Dockerfile
deleted file mode 100644
index 983eb89..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-sinks-internal-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/pom.xml b/streampipes-extensions/streampipes-sinks-internal-jvm/pom.xml
index 1262f52..0ceb2d8 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -30,28 +30,33 @@
     <properties>
         <lightcouch.version>0.1.8</lightcouch.version>
         <influxdb.java.version>2.14</influxdb.java.version>
-        <maven.deploy.skip>true</maven.deploy.skip>
     </properties>
 
     <dependencies>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-elements-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-data-explorer-commons</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
+        <!-- TODO remove after refactoring -->
         <dependency>
             <groupId>org.lightcouch</groupId>
             <artifactId>lightcouch</artifactId>
@@ -60,6 +65,8 @@
             <groupId>org.influxdb</groupId>
             <artifactId>influxdb-java</artifactId>
         </dependency>
+        <!-- TODO remove after refactoring -->
+
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
@@ -72,37 +79,6 @@
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-pool2</artifactId>
         </dependency>
-    </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-sinks-internal-jvm</finalName>
-    </build>
+    </dependencies>
 </project>
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/SinksInternalJvmInit.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/SinksInternalJvmInit.java
index 53e3db7..421ab74 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/SinksInternalJvmInit.java
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/SinksInternalJvmInit.java
@@ -21,6 +21,8 @@
 import org.apache.streampipes.container.model.SpServiceDefinition;
 import org.apache.streampipes.container.model.SpServiceDefinitionBuilder;
 import org.apache.streampipes.container.standalone.init.StandaloneModelSubmitter;
+import org.apache.streampipes.dataexplorer.commons.configs.CouchDbConfigurations;
+import org.apache.streampipes.dataexplorer.commons.configs.DataExplorerConfigurations;
 import org.apache.streampipes.dataformat.cbor.CborDataFormatFactory;
 import org.apache.streampipes.dataformat.fst.FstDataFormatFactory;
 import org.apache.streampipes.dataformat.json.JsonDataFormatFactory;
@@ -28,16 +30,11 @@
 import org.apache.streampipes.messaging.jms.SpJmsProtocolFactory;
 import org.apache.streampipes.messaging.kafka.SpKafkaProtocolFactory;
 import org.apache.streampipes.messaging.mqtt.SpMqttProtocolFactory;
-import org.apache.streampipes.sinks.internal.jvm.config.ConfigKeys;
-import org.apache.streampipes.sinks.internal.jvm.datalake.DataLakeController;
-import org.apache.streampipes.sinks.internal.jvm.notification.NotificationController;
+import org.apache.streampipes.sinks.internal.jvm.datalake.DataLakeSink;
+import org.apache.streampipes.sinks.internal.jvm.notification.NotificationProducer;
 
 public class SinksInternalJvmInit extends StandaloneModelSubmitter {
 
-  public static void main(String[] args) {
-    new SinksInternalJvmInit().init();
-  }
-
   @Override
   public SpServiceDefinition provideServiceDefinition() {
     return SpServiceDefinitionBuilder.create("org.apache.streampipes.sinks.internal.jvm",
@@ -45,8 +42,8 @@
             "",
             8090)
             .registerPipelineElements(
-                    new DataLakeController(),
-                    new NotificationController())
+                    new DataLakeSink(),
+                    new NotificationProducer())
             .registerMessagingFormats(
                     new JsonDataFormatFactory(),
                     new CborDataFormatFactory(),
@@ -56,15 +53,8 @@
                     new SpKafkaProtocolFactory(),
                     new SpJmsProtocolFactory(),
                     new SpMqttProtocolFactory())
-            .addConfig(ConfigKeys.COUCHDB_HOST, "couchdb", "Hostname for CouchDB to store image blobs")
-            .addConfig(ConfigKeys.COUCHDB_PORT, 5984, "")
-            .addConfig(ConfigKeys.COUCHDB_PROTOCOL, "http", "")
-            .addConfig(ConfigKeys.DATA_LAKE_HOST, "influxdb", "Hostname for the StreamPipes data lake database")
-            .addConfig(ConfigKeys.DATA_LAKE_PROTOCOL, "http", "Protocol for the StreamPipes data lake database")
-            .addConfig(ConfigKeys.DATA_LAKE_PORT, 8086, "Port for the StreamPipes data lake database")
-            .addConfig(ConfigKeys.DATA_LAKE_USERNAME, "default", "Username for the StreamPipes data lake database")
-            .addConfig(ConfigKeys.DATA_LAKE_PASSWORD, "default", "Password for the StreamPipes data lake database")
-            .addConfig(ConfigKeys.DATA_LAKE_DATABASE_NAME, "sp", "Database name for the StreamPipes data lake database")
+            .addConfigs(DataExplorerConfigurations.getDefaults())
+            .addConfigs(CouchDbConfigurations.getDefaults())
             .build();
 
 
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLake.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLake.java
deleted file mode 100644
index 83cbb3b..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLake.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.datalake;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.streampipes.client.StreamPipesClient;
-import org.apache.streampipes.commons.exceptions.SpRuntimeException;
-import org.apache.streampipes.logging.api.Logger;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.model.schema.EventProperty;
-import org.apache.streampipes.model.schema.EventSchema;
-import org.apache.streampipes.sinks.internal.jvm.config.ConfigKeys;
-import org.apache.streampipes.svcdiscovery.api.SpConfig;
-import org.apache.streampipes.vocabulary.SPSensor;
-import org.apache.streampipes.wrapper.context.EventSinkRuntimeContext;
-import org.apache.streampipes.wrapper.runtime.EventSink;
-
-import java.util.List;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
-/**
- * Code is the same as InfluxDB (org.apache.streampipes.sinks.databases.jvm.influxdb) sink. Changes applied here should also be applied in the InfluxDB sink
- */
-public class DataLake implements EventSink<DataLakeParameters> {
-
-
-  private DataLakeInfluxDbClient influxDbClient;
-
-  private static Logger LOG;
-
-  private List<EventProperty> imageProperties;
-  private String timestampField;
-
-  private EventSchema eventSchema;
-  private ImageStore imageStore;
-
-  @Override
-  public void onInvocation(DataLakeParameters parameters, EventSinkRuntimeContext runtimeContext) throws SpRuntimeException {
-    LOG = parameters.getGraph().getLogger(DataLake.class);
-
-    this.timestampField = parameters.getTimestampField();
-
-    SpConfig configStore = runtimeContext.getConfigStore().getConfig();
-
-    String influxHost = configStore.getString(ConfigKeys.DATA_LAKE_PROTOCOL) + "://" + configStore.getString(ConfigKeys.DATA_LAKE_HOST);
-    Integer influxPort = configStore.getInteger(ConfigKeys.DATA_LAKE_PORT);
-    String databaseName = configStore.getString(ConfigKeys.DATA_LAKE_DATABASE_NAME);
-    String user = configStore.getString(ConfigKeys.DATA_LAKE_USERNAME);
-    String password = configStore.getString(ConfigKeys.DATA_LAKE_PASSWORD);
-
-    String couchDbProtocol = configStore.getString(ConfigKeys.COUCHDB_PROTOCOL);
-    String couchDbHost = configStore.getString(ConfigKeys.COUCHDB_HOST);
-    int couchDbPort = configStore.getInteger(ConfigKeys.COUCHDB_PORT);
-
-    this.imageStore = new ImageStore(couchDbProtocol, couchDbHost, couchDbPort);
-
-    EventSchema schema = runtimeContext.getInputSchemaInfo().get(0).getEventSchema();
-    // Remove the timestamp field from the event schema
-    List<EventProperty> eventPropertiesWithoutTimestamp = schema.getEventProperties()
-            .stream()
-            .filter(eventProperty -> !this.timestampField.endsWith(eventProperty.getRuntimeName()))
-            .collect(Collectors.toList());
-    schema.setEventProperties(eventPropertiesWithoutTimestamp);
-
-    // deep copy of event schema. Event property runtime name is changed to lower case for the schema registration
-    this.eventSchema = new EventSchema(schema);
-
-    schema.getEventProperties().forEach(eventProperty ->
-            eventProperty.setRuntimeName(DataLakeUtils.sanitizePropertyRuntimeName(eventProperty.getRuntimeName())));
-    registerAtDataLake(parameters.getMeasurementName(), schema, runtimeContext.getStreamPipesClient());
-
-    imageProperties = schema.getEventProperties().stream()
-            .filter(eventProperty -> eventProperty.getDomainProperties() != null &&
-                    eventProperty.getDomainProperties().size() > 0 &&
-                    eventProperty.getDomainProperties().get(0).toString().equals(SPSensor.IMAGE))
-            .collect(Collectors.toList());
-
-    InfluxDbConnectionSettings settings = InfluxDbConnectionSettings.from(
-            influxHost, influxPort, databaseName, parameters.getMeasurementName(), user, password);
-
-    this.influxDbClient = new DataLakeInfluxDbClient(
-            settings,
-            parameters.getTimestampField(),
-            parameters.getBatchSize(),
-            parameters.getFlushDuration(),
-            this.eventSchema
-    );
-  }
-
-  @Override
-  public void onEvent(Event event) {
-    try {
-
-      this.imageProperties.forEach(eventProperty -> {
-        String imageDocId = UUID.randomUUID().toString();
-        String image = event.getFieldByRuntimeName(eventProperty.getRuntimeName()).getAsPrimitive().getAsString();
-
-        this.writeToImageFile(image, imageDocId);
-        event.updateFieldBySelector("s0::" + eventProperty.getRuntimeName(), imageDocId);
-      });
-
-      influxDbClient.save(event, this.eventSchema);
-    } catch (SpRuntimeException e) {
-      LOG.error(e.getMessage());
-    }
-  }
-
-  @Override
-  public void onDetach() throws SpRuntimeException {
-    influxDbClient.stop();
-  }
-
-  private void writeToImageFile(String image, String imageDocId) {
-    byte[] data = Base64.decodeBase64(image);
-    this.imageStore.storeImage(data, imageDocId);
-  }
-
-  /**
-   * Adds a new measurement to the StreamPipes data lake
-   * @param measure
-   * @param eventSchema
-   * @throws SpRuntimeException
-   */
-  private void registerAtDataLake(String measure,
-                                  EventSchema eventSchema,
-                                  StreamPipesClient client) throws SpRuntimeException {
-      client
-        .customRequest()
-        .sendPost("api/v3/datalake/measure/" + measure, eventSchema);
-  }
-
-
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeController.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeController.java
deleted file mode 100644
index 6bdad66..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeController.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.datalake;
-
-import org.apache.streampipes.model.DataSinkType;
-import org.apache.streampipes.model.graph.DataSinkDescription;
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.model.schema.PropertyScope;
-import org.apache.streampipes.sdk.builder.DataSinkBuilder;
-import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
-import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor;
-import org.apache.streampipes.sdk.helpers.EpRequirements;
-import org.apache.streampipes.sdk.helpers.Labels;
-import org.apache.streampipes.sdk.helpers.Locales;
-import org.apache.streampipes.sdk.utils.Assets;
-import org.apache.streampipes.wrapper.standalone.ConfiguredEventSink;
-import org.apache.streampipes.wrapper.standalone.declarer.StandaloneEventSinkDeclarer;
-
-public class DataLakeController extends StandaloneEventSinkDeclarer<DataLakeParameters> {
-
-  private static final String DATABASE_MEASUREMENT_KEY = "db_measurement";
-  private static final String TIMESTAMP_MAPPING_KEY = "timestamp_mapping";
-
-
-  @Override
-  public DataSinkDescription declareModel() {
-    return DataSinkBuilder.create("org.apache.streampipes.sinks.internal.jvm.datalake")
-            .withLocales(Locales.EN)
-            .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-            .category(DataSinkType.INTERNAL)
-            .requiredStream(StreamRequirementsBuilder.create().requiredPropertyWithUnaryMapping(
-                    EpRequirements.timestampReq(),
-                    Labels.withId(TIMESTAMP_MAPPING_KEY),
-                    PropertyScope.NONE).build())
-            .requiredTextParameter(Labels.withId(DATABASE_MEASUREMENT_KEY))
-            .build();
-  }
-
-  @Override
-  public ConfiguredEventSink<DataLakeParameters> onInvocation(DataSinkInvocation graph,
-                                                              DataSinkParameterExtractor extractor) {
-
-    String measureName = extractor.singleValueParameter(DATABASE_MEASUREMENT_KEY, String.class);
-    measureName = DataLakeUtils.prepareString(measureName);
-    String timestampField = extractor.mappingPropertyValue(TIMESTAMP_MAPPING_KEY);
-
-    Integer batch_size = 2000;
-    Integer flush_duration = 500;
-
-    DataLakeParameters params = new DataLakeParameters(graph,
-            measureName,
-            timestampField,
-            batch_size,
-            flush_duration);
-
-
-    return new ConfiguredEventSink<>(params, DataLake::new);
-  }
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeInfluxDbClient.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeInfluxDbClient.java
deleted file mode 100644
index 80c7214..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeInfluxDbClient.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.datalake;
-
-import org.apache.streampipes.commons.exceptions.SpRuntimeException;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.model.runtime.field.PrimitiveField;
-import org.apache.streampipes.model.schema.EventProperty;
-import org.apache.streampipes.model.schema.EventPropertyPrimitive;
-import org.apache.streampipes.model.schema.EventSchema;
-import org.apache.streampipes.vocabulary.XSD;
-import org.influxdb.InfluxDB;
-import org.influxdb.InfluxDBFactory;
-import org.influxdb.dto.Point;
-import org.influxdb.dto.Pong;
-import org.influxdb.dto.Query;
-import org.influxdb.dto.QueryResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Code is the same as InfluxDB (org.apache.streampipes.sinks.databases.jvm.influxdb) sink. Changes applied here should also be applied in the InfluxDB sink
- */
-public class DataLakeInfluxDbClient {
-
-    private static final Logger LOG = LoggerFactory.getLogger(DataLakeInfluxDbClient.class);
-
-    private final String measureName;
-    private final String timestampField;
-    private final Integer batchSize;
-    private final Integer flushDuration;
-
-    private InfluxDB influxDb = null;
-    private final InfluxDbConnectionSettings settings;
-    private final EventSchema originalEventSchema;
-
-    Map<String, String> targetRuntimeNames = new HashMap<>();
-
-    DataLakeInfluxDbClient(InfluxDbConnectionSettings settings,
-                           String timestampField,
-                           Integer batchSize,
-                           Integer flushDuration,
-                           EventSchema originalEventSchema) throws SpRuntimeException {
-        this.settings = settings;
-        this.originalEventSchema = originalEventSchema;
-        this.timestampField = timestampField;
-        this.batchSize = batchSize;
-        this.flushDuration = flushDuration;
-        this.measureName = settings.getMeasureName();
-
-        prepareSchema();
-        connect();
-    }
-
-    private void prepareSchema() {
-        originalEventSchema
-                .getEventProperties()
-                .forEach(ep -> targetRuntimeNames.put(ep.getRuntimeName(), DataLakeUtils.sanitizePropertyRuntimeName(ep.getRuntimeName())));
-    }
-
-    /**
-     * Connects to the InfluxDB Server, sets the database and initializes the batch-behaviour
-     *
-     * @throws SpRuntimeException If not connection can be established or if the database could not
-     * be found
-     */
-    private void connect() throws SpRuntimeException {
-        // Connecting to the server
-        // "http://" must be in front
-        String urlAndPort = settings.getInfluxDbHost() + ":" + settings.getInfluxDbPort();
-        influxDb = InfluxDBFactory.connect(urlAndPort, settings.getUser(), settings.getPassword());
-
-        // Checking, if server is available
-        Pong response = influxDb.ping();
-        if (response.getVersion().equalsIgnoreCase("unknown")) {
-            throw new SpRuntimeException("Could not connect to InfluxDb Server: " + urlAndPort);
-        }
-
-        String databaseName = settings.getDatabaseName();
-        // Checking whether the database exists
-        if(!databaseExists(databaseName)) {
-            LOG.info("Database '" + databaseName + "' not found. Gets created ...");
-            createDatabase(databaseName);
-        }
-
-        // setting up the database
-        influxDb.setDatabase(databaseName);
-        influxDb.enableBatch(batchSize, flushDuration, TimeUnit.MILLISECONDS);
-    }
-
-    /**
-     * Checks whether the given database exists. Needs a working connection to an InfluxDB Server
-     * ({@link DataLakeInfluxDbClient#influxDb} needs to be initialized)
-     *
-     * @param dbName The name of the database, the method should look for
-     * @return True if the database exists, false otherwise
-     */
-    private boolean databaseExists(String dbName) {
-        QueryResult queryResult = influxDb.query(new Query("SHOW DATABASES", ""));
-        for(List<Object> a : queryResult.getResults().get(0).getSeries().get(0).getValues()) {
-            if(a.get(0).equals(dbName)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Creates a new database with the given name
-     *
-     * @param dbName The name of the database which should be created
-     */
-    private void createDatabase(String dbName) throws SpRuntimeException {
-        if(!dbName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$")) {
-            throw new SpRuntimeException("Databasename '" + dbName + "' not allowed. Allowed names: ^[a-zA-Z_][a-zA-Z0-9_]*$");
-        }
-        influxDb.query(new Query("CREATE DATABASE \"" + dbName + "\"", ""));
-    }
-
-    /**
-     * Saves an event to the connnected InfluxDB database
-     *
-     * @param event The event which should be saved
-     * @throws SpRuntimeException If the column name (key-value of the event map) is not allowed
-     */
-    void save(Event event, EventSchema schema) throws SpRuntimeException {
-        if (event == null) {
-            throw new SpRuntimeException("event is null");
-        }
-
-        Long timestampValue = event.getFieldBySelector(timestampField).getAsPrimitive().getAsLong();
-        Point.Builder p = Point.measurement(measureName).time(timestampValue, TimeUnit.MILLISECONDS);
-
-        for (EventProperty ep : schema.getEventProperties()) {
-            if (ep instanceof EventPropertyPrimitive) {
-                String runtimeName = ep.getRuntimeName();
-
-                if (!timestampField.endsWith(runtimeName)) {
-                    String preparedRuntimeName = targetRuntimeNames.get(runtimeName);
-                    PrimitiveField eventPropertyPrimitiveField = event.getFieldByRuntimeName(runtimeName).getAsPrimitive();
-
-                    // store property as tag when the field is a dimension property
-                    if ("DIMENSION_PROPERTY".equals(ep.getPropertyScope())) {
-                        p.tag(preparedRuntimeName, eventPropertyPrimitiveField.getAsString());
-                    } else {
-                        try {
-                            // Store property according to property type
-                            String runtimeType = ((EventPropertyPrimitive) ep).getRuntimeType();
-                            if (XSD._integer.toString().equals(runtimeType)) {
-                                p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsInt());
-                            } else if (XSD._float.toString().equals(runtimeType)) {
-                                p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsFloat());
-                            } else if (XSD._double.toString().equals(runtimeType)) {
-                                p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsDouble());
-                            } else if (XSD._boolean.toString().equals(runtimeType)) {
-                                p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsBoolean());
-                            } else if (XSD._long.toString().equals(runtimeType)) {
-                                p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsLong());
-                            } else {
-                                p.addField(preparedRuntimeName, eventPropertyPrimitiveField.getAsString());
-                            }
-                        } catch (NumberFormatException e) {
-                            LOG.warn("Wrong number format for field {}, ignoring.", preparedRuntimeName);
-                        }
-                    }
-                }
-            }
-        }
-
-        influxDb.write(p.build());
-    }
-
-    /**
-     * Shuts down the connection to the InfluxDB server
-     */
-    void stop() {
-        influxDb.flush();
-        try {
-            Thread.sleep(1000);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        influxDb.close();
-    }
-
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeParameters.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeParameters.java
deleted file mode 100644
index 61f8f3a..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeParameters.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.datalake;
-
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.wrapper.params.binding.EventSinkBindingParams;
-
-/**
- * Code is the same as InfluxDB (org.apache.streampipes.sinks.databases.jvm.influxdb) sink. Changes applied here should also be applied in the InfluxDB sink
- */
-public class DataLakeParameters extends EventSinkBindingParams {
-
-  private String measureName;
-  private String timestampField;
-  private Integer batchSize;
-  private Integer flushDuration;
-
-  public DataLakeParameters(DataSinkInvocation graph,
-                            String measureName,
-                            String timestampField,
-                            Integer batchSize,
-                            Integer flushDuration) {
-    super(graph);
-    this.measureName = measureName;
-    this.timestampField = timestampField;
-    this.batchSize = batchSize;
-    this.flushDuration = flushDuration;
-  }
-
-  public String getMeasurementName() {
-    return measureName;
-  }
-
-  public String getTimestampField() {
-    return timestampField;
-  }
-
-  public Integer getBatchSize() {
-    return batchSize;
-  }
-
-  public Integer getFlushDuration() {
-    return flushDuration;
-  }
-
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeSink.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeSink.java
new file mode 100644
index 0000000..a62315b
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeSink.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.sinks.internal.jvm.datalake;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.dataexplorer.commons.TimeSeriesStore;
+import org.apache.streampipes.logging.api.Logger;
+import org.apache.streampipes.model.DataSinkType;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.graph.DataSinkDescription;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.EventSchema;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.sdk.builder.DataSinkBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.helpers.EpRequirements;
+import org.apache.streampipes.sdk.helpers.Labels;
+import org.apache.streampipes.sdk.helpers.Locales;
+import org.apache.streampipes.sdk.utils.Assets;
+import org.apache.streampipes.wrapper.context.EventSinkRuntimeContext;
+import org.apache.streampipes.wrapper.standalone.SinkParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataSink;
+
+
+public class DataLakeSink extends StreamPipesDataSink {
+    private static Logger LOG;
+
+    private static final String DATABASE_MEASUREMENT_KEY = "db_measurement";
+    private static final String TIMESTAMP_MAPPING_KEY = "timestamp_mapping";
+
+    private TimeSeriesStore timeSeriesStore;
+
+
+    @Override
+    public DataSinkDescription declareModel() {
+        return DataSinkBuilder.create("org.apache.streampipes.sinks.internal.jvm.datalake")
+          .withLocales(Locales.EN)
+          .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+          .category(DataSinkType.INTERNAL)
+          .requiredStream(StreamRequirementsBuilder.create()
+            .requiredPropertyWithUnaryMapping(
+                EpRequirements.timestampReq(),
+                Labels.withId(TIMESTAMP_MAPPING_KEY),
+                PropertyScope.NONE)
+                .build())
+          .requiredTextParameter(Labels.withId(DATABASE_MEASUREMENT_KEY))
+          .build();
+    }
+
+    @Override
+    public void onInvocation(SinkParams parameters, EventSinkRuntimeContext runtimeContext) throws SpRuntimeException {
+
+
+        LOG = parameters.getGraph().getLogger(DataLakeSink.class);
+
+        String timestampField = parameters.extractor().mappingPropertyValue(TIMESTAMP_MAPPING_KEY);
+        String measureName = parameters.extractor().singleValueParameter(DATABASE_MEASUREMENT_KEY, String.class);
+        EventSchema eventSchema = runtimeContext.getInputSchemaInfo().get(0).getEventSchema();
+
+        DataLakeMeasure measure = new DataLakeMeasure(measureName, timestampField, eventSchema);
+
+        this.timeSeriesStore = new TimeSeriesStore(runtimeContext.getConfigStore().getConfig(),
+          runtimeContext.getStreamPipesClient(),
+          measure,
+          true);
+
+    }
+
+    @Override
+    public void onEvent(Event event) throws SpRuntimeException {
+        this.timeSeriesStore.onEvent(event);
+    }
+
+    @Override
+    public void onDetach() throws SpRuntimeException {
+        this.timeSeriesStore.close();
+    }
+}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeUtils.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeUtils.java
deleted file mode 100644
index 8fa1736..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeUtils.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.datalake;
-
-public class DataLakeUtils {
-
-  public static String prepareString(String s) {
-    return s.toLowerCase().replaceAll(" ", "_");
-  }
-
-  private static String renameReservedKeywords(String runtimeName) {
-    if (InfluxDbReservedKeywords.keywordList.stream().anyMatch(k -> k.equalsIgnoreCase(runtimeName))) {
-      return runtimeName + "_";
-    } else {
-      return runtimeName;
-    }
-  }
-
-  public static String sanitizePropertyRuntimeName(String runtimeName) {
-    String sanitizedRuntimeName = prepareString(runtimeName);
-    return renameReservedKeywords(sanitizedRuntimeName);
-  }
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/ImageStore.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/ImageStore.java
deleted file mode 100644
index cd946b4..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/ImageStore.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.datalake;
-
-import org.lightcouch.CouchDbClient;
-import org.lightcouch.CouchDbProperties;
-
-import java.io.ByteArrayInputStream;
-
-public class ImageStore {
-
-  private static final String DB_NAME = "images";
-
-  private CouchDbClient couchDbClient;
-
-  public ImageStore(String couchDbProtocol,
-                    String couchDbHost,
-                    int couchDbPort) {
-    this.couchDbClient = new CouchDbClient(props(couchDbProtocol, couchDbHost, couchDbPort));
-  }
-
-  public void storeImage(byte[] imageBytes,
-                         String imageDocId) {
-    this.couchDbClient.saveAttachment(
-            new ByteArrayInputStream(imageBytes),
-            imageDocId,
-            "image/jpeg",
-            imageDocId,
-            null);
-  }
-
-  private static CouchDbProperties props(String couchDbProtocol,
-                                         String couchDbHost,
-                                         int couchDbPort) {
-    return new CouchDbProperties(DB_NAME, true, couchDbProtocol,
-            couchDbHost, couchDbPort, null, null);
-  }
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/InfluxDbConnectionSettings.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/InfluxDbConnectionSettings.java
deleted file mode 100644
index 3be6b21..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/InfluxDbConnectionSettings.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.datalake;
-
-public class InfluxDbConnectionSettings {
-
-  private final Integer influxDbPort;
-  private final String influxDbHost;
-  private final String databaseName;
-  private final String measureName;
-  private final String user;
-  private final String password;
-
-  public static InfluxDbConnectionSettings from(String influxDbHost,
-                                                Integer influxDbPort,
-                                                String databaseName,
-                                                String measureName,
-                                                String user,
-                                                String password) {
-    return new InfluxDbConnectionSettings(
-            influxDbHost,
-            influxDbPort,
-            databaseName,
-            measureName,
-            user,
-            password);
-  }
-
-  private InfluxDbConnectionSettings(String influxDbHost,
-                                     Integer influxDbPort,
-                                     String databaseName,
-                                     String measureName,
-                                     String user,
-                                     String password) {
-    this.influxDbHost = influxDbHost;
-    this.influxDbPort = influxDbPort;
-    this.databaseName = databaseName;
-    this.measureName = measureName;
-    this.user = user;
-    this.password = password;
-  }
-
-  public Integer getInfluxDbPort() {
-    return influxDbPort;
-  }
-
-  public String getInfluxDbHost() {
-    return influxDbHost;
-  }
-
-  public String getDatabaseName() {
-    return databaseName;
-  }
-
-  public String getMeasureName() {
-    return measureName;
-  }
-
-  public String getUser() {
-    return user;
-  }
-
-  public String getPassword() {
-    return password;
-  }
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationController.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationController.java
deleted file mode 100644
index d9cd341..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.notification;
-
-import org.apache.streampipes.model.DataSinkType;
-import org.apache.streampipes.model.graph.DataSinkDescription;
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.sdk.builder.DataSinkBuilder;
-import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
-import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor;
-import org.apache.streampipes.sdk.helpers.EpRequirements;
-import org.apache.streampipes.sdk.helpers.Labels;
-import org.apache.streampipes.sdk.helpers.Locales;
-import org.apache.streampipes.sdk.utils.Assets;
-import org.apache.streampipes.wrapper.standalone.ConfiguredEventSink;
-import org.apache.streampipes.wrapper.standalone.declarer.StandaloneEventSinkDeclarer;
-
-public class NotificationController extends StandaloneEventSinkDeclarer<NotificationParameters> {
-
-  private static final String TITLE_KEY = "title";
-  private static final String CONTENT_KEY = "content";
-
-  @Override
-  public DataSinkDescription declareModel() {
-    return DataSinkBuilder.create("org.apache.streampipes.sinks.internal.jvm.notification")
-            .withLocales(Locales.EN)
-            .withAssets(Assets.DOCUMENTATION, Assets.ICON)
-            .category(DataSinkType.INTERNAL, DataSinkType.NOTIFICATION)
-            .requiredStream(StreamRequirementsBuilder
-                    .create()
-                    .requiredProperty(EpRequirements.anyProperty())
-                    .build())
-            .requiredTextParameter(Labels.withId(TITLE_KEY))
-            .requiredHtmlInputParameter(Labels.withId(CONTENT_KEY))
-            .build();
-  }
-
-  @Override
-  public ConfiguredEventSink<NotificationParameters> onInvocation(DataSinkInvocation graph,
-                                                                  DataSinkParameterExtractor extractor) {
-
-    String title = extractor.singleValueParameter(TITLE_KEY, String.class);
-    String content = extractor.singleValueParameter(CONTENT_KEY, String.class);
-
-    NotificationParameters params = new NotificationParameters(graph, title, content);
-
-    return new ConfiguredEventSink<>(params, NotificationProducer::new);
-  }
-
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationParameters.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationParameters.java
deleted file mode 100644
index 2914433..0000000
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationParameters.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.sinks.internal.jvm.notification;
-
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.wrapper.params.binding.EventSinkBindingParams;
-
-public class NotificationParameters extends EventSinkBindingParams {
-
-  private String title;
-  private String content;
-
-  public NotificationParameters(DataSinkInvocation graph, String title, String content) {
-    super(graph);
-    this.title = title;
-    this.content = content;
-  }
-
-  public String getTitle() {
-    return title;
-  }
-
-  public String getContent() {
-    return content;
-  }
-}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationProducer.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationProducer.java
index c7bcad0..74ebd34 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationProducer.java
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/notification/NotificationProducer.java
@@ -21,21 +21,38 @@
 
 import org.apache.streampipes.client.StreamPipesClient;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.model.DataSinkType;
 import org.apache.streampipes.model.Notification;
+import org.apache.streampipes.model.graph.DataSinkDescription;
 import org.apache.streampipes.model.runtime.Event;
 import org.apache.streampipes.pe.shared.PlaceholderExtractor;
+import org.apache.streampipes.sdk.builder.DataSinkBuilder;
+import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
+import org.apache.streampipes.sdk.helpers.EpRequirements;
+import org.apache.streampipes.sdk.helpers.Labels;
+import org.apache.streampipes.sdk.helpers.Locales;
+import org.apache.streampipes.sdk.utils.Assets;
 import org.apache.streampipes.wrapper.context.EventSinkRuntimeContext;
-import org.apache.streampipes.wrapper.runtime.EventSink;
+import org.apache.streampipes.wrapper.standalone.SinkParams;
+import org.apache.streampipes.wrapper.standalone.StreamPipesDataSink;
 
+import java.time.Instant;
 import java.util.Date;
 import java.util.UUID;
 
-public class NotificationProducer implements EventSink<NotificationParameters> {
+public class NotificationProducer extends StreamPipesDataSink {
 
   private static final String HASHTAG = "#";
+  private static final String TITLE_KEY = "title";
+  private static final String CONTENT_KEY = "content";
+  private static final String SILENT_PERIOD = "silent-period";
 
   private String title;
   private String content;
+
+  private long silentPeriodInSeconds;
+  private long lastMessageEpochSecond = -1;
+
   private String correspondingPipelineId;
   private String correspondingUser;
 
@@ -43,10 +60,11 @@
 
 
   @Override
-  public void onInvocation(NotificationParameters parameters, EventSinkRuntimeContext context) throws
+  public void onInvocation(SinkParams parameters, EventSinkRuntimeContext context) throws
           SpRuntimeException {
-    this.title = parameters.getTitle();
-    this.content = parameters.getContent();
+    this.title = parameters.extractor().singleValueParameter(TITLE_KEY, String.class);
+    this.content = parameters.extractor().singleValueParameter(CONTENT_KEY, String.class);
+    this.silentPeriodInSeconds = parameters.extractor().singleValueParameter(SILENT_PERIOD, Integer.class) * 60;
     this.correspondingPipelineId = parameters.getGraph().getCorrespondingPipeline();
     this.correspondingUser = parameters.getGraph().getCorrespondingUser();
     this.client = context.getStreamPipesClient();
@@ -54,20 +72,23 @@
 
   @Override
   public void onEvent(Event inputEvent) {
-    Date currentDate = new Date();
-    Notification notification = new Notification();
-    notification.setId(UUID.randomUUID().toString());
-    notification.setRead(false);
-    notification.setTitle(title);
-    notification.setMessage(PlaceholderExtractor.replacePlaceholders(inputEvent, content));
-    notification.setCreatedAt(currentDate);
-    notification.setCreatedAtTimestamp(currentDate.getTime());
-    notification.setCorrespondingPipelineId(correspondingPipelineId);
-    notification.setTargetedAt(correspondingUser);
+    if (shouldSendNotification()) {
+      Date currentDate = new Date();
+      Notification notification = new Notification();
+      notification.setId(UUID.randomUUID().toString());
+      notification.setRead(false);
+      notification.setTitle(title);
+      notification.setMessage(PlaceholderExtractor.replacePlaceholders(inputEvent, content));
+      notification.setCreatedAt(currentDate);
+      notification.setCreatedAtTimestamp(currentDate.getTime());
+      notification.setCorrespondingPipelineId(correspondingPipelineId);
+      notification.setTargetedAt(correspondingUser);
 
-    // TODO add targeted user to notification object
+      // TODO add targeted user to notification object
 
-    client.notificationsApi().add(notification);
+      client.notificationsApi().add(notification);
+      this.lastMessageEpochSecond = Instant.now().getEpochSecond();
+    }
   }
 
   @Override
@@ -75,4 +96,27 @@
 
   }
 
+  private boolean shouldSendNotification() {
+    if (this.lastMessageEpochSecond == -1) {
+      return true;
+    } else {
+      return Instant.now().getEpochSecond() >= (this.lastMessageEpochSecond + this.silentPeriodInSeconds);
+    }
+  }
+
+  @Override
+  public DataSinkDescription declareModel() {
+    return DataSinkBuilder.create("org.apache.streampipes.sinks.internal.jvm.notification")
+      .withLocales(Locales.EN)
+      .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+      .category(DataSinkType.INTERNAL, DataSinkType.NOTIFICATION)
+      .requiredStream(StreamRequirementsBuilder
+        .create()
+        .requiredProperty(EpRequirements.anyProperty())
+        .build())
+      .requiredTextParameter(Labels.withId(TITLE_KEY))
+      .requiredHtmlInputParameter(Labels.withId(CONTENT_KEY))
+      .requiredIntegerParameter(Labels.withId(SILENT_PERIOD), 10)
+      .build();
+  }
 }
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.notification/strings.en b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.notification/strings.en
index b64ef71..886235d 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.notification/strings.en
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.notification/strings.en
@@ -6,3 +6,6 @@
 
 content.title=Content
 content.description=Enter the notification text. You can  use placeholders like #fieldName# to add the value of a stream variable.
+
+silent-period.title=Silent Period [min]
+silent-period.description=The minimum number of minutes between two consecutive notifications that are sent.
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/Dockerfile b/streampipes-extensions/streampipes-sinks-notifications-jvm/Dockerfile
deleted file mode 100644
index 0b594df..0000000
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY target/streampipes-sinks-notifications-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/aarch64.Dockerfile b/streampipes-extensions/streampipes-sinks-notifications-jvm/aarch64.Dockerfile
deleted file mode 100644
index 499af11..0000000
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-sinks-notifications-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/arm.Dockerfile b/streampipes-extensions/streampipes-sinks-notifications-jvm/arm.Dockerfile
deleted file mode 100644
index 2edc3d8..0000000
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-sinks-notifications-jvm.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/development/env b/streampipes-extensions/streampipes-sinks-notifications-jvm/development/env
deleted file mode 100644
index b575485..0000000
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/development/env
+++ /dev/null
@@ -1,28 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Those parameters are used by IntelliJ to set the default consul parameters for development
-SP_PORT=7025
-SP_HOST=host.docker.internal
-SP_DEBUG=true
-SLACK_TOKEN=
-EMAIL_FROM=
-EMAIL_USERNAME=
-EMAIL_PASSWORD=
-EMAIL_SMTP_HOST=
-EMAIL_SMTP_PORT=
-EMAIL_STARTTLS=
-EMAIL_SLL=
-WEBSOCKET_PROTOCOL=ws
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/pom.xml b/streampipes-extensions/streampipes-sinks-notifications-jvm/pom.xml
index 0b1fb39..d21329f 100644
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/pom.xml
@@ -21,32 +21,28 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>streampipes-sinks-notifications-jvm</artifactId>
 
-    <properties>
-        <maven.deploy.skip>true</maven.deploy.skip>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-elements-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -64,36 +60,4 @@
         </dependency>
     </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <phase>package</phase>
-                        <configuration>
-                            <classifier>embed</classifier>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <finalName>streampipes-sinks-notifications-jvm</finalName>
-
-    </build>
 </project>
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/SinksNotificationsJvmInit.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/SinksNotificationsJvmInit.java
index 019cb4b..72a6dd4 100644
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/SinksNotificationsJvmInit.java
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/SinksNotificationsJvmInit.java
@@ -36,10 +36,6 @@
 
 public class SinksNotificationsJvmInit extends StandaloneModelSubmitter {
 
-  public static void main(String[] args) {
-        new SinksNotificationsJvmInit().init();
-  }
-
   @Override
   public SpServiceDefinition provideServiceDefinition() {
     return SpServiceDefinitionBuilder.create("org.apache.streampipes.sinks.notifications.jvm",
diff --git a/streampipes-extensions/streampipes-sources-vehicle-simulator/Dockerfile b/streampipes-extensions/streampipes-sources-vehicle-simulator/Dockerfile
index 924db56..c8f7b92 100644
--- a/streampipes-extensions/streampipes-sources-vehicle-simulator/Dockerfile
+++ b/streampipes-extensions/streampipes-sources-vehicle-simulator/Dockerfile
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
+FROM eclipse-temurin:11-jre-focal
 
 ENV CONSUL_LOCATION consul
 
diff --git a/streampipes-extensions/streampipes-sources-vehicle-simulator/aarch64.Dockerfile b/streampipes-extensions/streampipes-sources-vehicle-simulator/aarch64.Dockerfile
deleted file mode 100644
index 97a15aa..0000000
--- a/streampipes-extensions/streampipes-sources-vehicle-simulator/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-sources-vehicle-simulator.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sources-vehicle-simulator/arm.Dockerfile b/streampipes-extensions/streampipes-sources-vehicle-simulator/arm.Dockerfile
deleted file mode 100644
index 0843e9e..0000000
--- a/streampipes-extensions/streampipes-sources-vehicle-simulator/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-sources-vehicle-simulator.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sources-vehicle-simulator/pom.xml b/streampipes-extensions/streampipes-sources-vehicle-simulator/pom.xml
index 81c6eee..b559567 100644
--- a/streampipes-extensions/streampipes-sources-vehicle-simulator/pom.xml
+++ b/streampipes-extensions/streampipes-sources-vehicle-simulator/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -35,7 +35,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-elements-data-simulator</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>log4j</groupId>
@@ -48,7 +48,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.graalvm.nativeimage</groupId>
@@ -59,12 +59,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sources</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-extensions/streampipes-sources-watertank-simulator/Dockerfile b/streampipes-extensions/streampipes-sources-watertank-simulator/Dockerfile
index 48b6778..12bee65 100644
--- a/streampipes-extensions/streampipes-sources-watertank-simulator/Dockerfile
+++ b/streampipes-extensions/streampipes-sources-watertank-simulator/Dockerfile
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-ARG BASE_IMAGE=adoptopenjdk/openjdk8-openj9:alpine
-FROM $BASE_IMAGE
+FROM eclipse-temurin:11-jre-focal
 
 ENV CONSUL_LOCATION consul
 
diff --git a/streampipes-extensions/streampipes-sources-watertank-simulator/aarch64.Dockerfile b/streampipes-extensions/streampipes-sources-watertank-simulator/aarch64.Dockerfile
deleted file mode 100644
index 77507a9..0000000
--- a/streampipes-extensions/streampipes-sources-watertank-simulator/aarch64.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm64v8/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-aarch64-static /usr/bin
-COPY target/streampipes-sources-watertank-simulator.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sources-watertank-simulator/arm.Dockerfile b/streampipes-extensions/streampipes-sources-watertank-simulator/arm.Dockerfile
deleted file mode 100644
index 0367081..0000000
--- a/streampipes-extensions/streampipes-sources-watertank-simulator/arm.Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ARG BASE_IMAGE=arm32v7/openjdk:11-jre-slim
-FROM $BASE_IMAGE
-
-ENV CONSUL_LOCATION consul
-
-EXPOSE 8090
-
-COPY qemu-arm-static /usr/bin
-COPY target/streampipes-sources-watertank-simulator.jar  /streampipes-processing-element-container.jar
-
-ENTRYPOINT ["java", "-jar", "/streampipes-processing-element-container.jar"]
diff --git a/streampipes-extensions/streampipes-sources-watertank-simulator/pom.xml b/streampipes-extensions/streampipes-sources-watertank-simulator/pom.xml
index 6e5da08..a1b8b40 100644
--- a/streampipes-extensions/streampipes-sources-watertank-simulator/pom.xml
+++ b/streampipes-extensions/streampipes-sources-watertank-simulator/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-extensions</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -35,7 +35,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-elements-data-simulator</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>log4j</groupId>
@@ -48,7 +48,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk-bundle</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.graalvm.nativeimage</groupId>
@@ -59,12 +59,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sources</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-logging/pom.xml b/streampipes-logging/pom.xml
index 1e8f567..bec0929 100644
--- a/streampipes-logging/pom.xml
+++ b/streampipes-logging/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/streampipes-mail/pom.xml b/streampipes-mail/pom.xml
index 782ce9d..8b50f0f 100644
--- a/streampipes-mail/pom.xml
+++ b/streampipes-mail/pom.xml
@@ -16,13 +16,11 @@
   ~ limitations under the License.
   ~
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +30,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-user-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.simplejavamail</groupId>
diff --git a/streampipes-maven-plugin/pom.xml b/streampipes-maven-plugin/pom.xml
index 3abf907..f711ab2 100644
--- a/streampipes-maven-plugin/pom.xml
+++ b/streampipes-maven-plugin/pom.xml
@@ -20,7 +20,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -139,7 +139,7 @@
         <dependency>
             <groupId>org.yaml</groupId>
             <artifactId>snakeyaml</artifactId>
-            <version>1.26</version>
+            <version>1.32</version>
         </dependency>
 
         <!-- dependency convergence -->
diff --git a/streampipes-measurement-units/pom.xml b/streampipes-measurement-units/pom.xml
index d2e700b..fd17344 100644
--- a/streampipes-measurement-units/pom.xml
+++ b/streampipes-measurement-units/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<groupId>org.apache.streampipes</groupId>
 		<artifactId>streampipes-parent</artifactId>
-		<version>0.70.0-SNAPSHOT</version>
+		<version>0.71.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>streampipes-measurement-units</artifactId>
@@ -31,7 +31,7 @@
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-commons</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 
 		<!-- External dependencies -->
diff --git a/streampipes-messaging-jms/pom.xml b/streampipes-messaging-jms/pom.xml
index 985aea4..3edcc5c 100644
--- a/streampipes-messaging-jms/pom.xml
+++ b/streampipes-messaging-jms/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
        <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,7 +32,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-messaging-kafka/pom.xml b/streampipes-messaging-kafka/pom.xml
index 2bdae81..2948501 100644
--- a/streampipes-messaging-kafka/pom.xml
+++ b/streampipes-messaging-kafka/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-commons</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-messaging-mqtt/pom.xml b/streampipes-messaging-mqtt/pom.xml
index 67ac177..d157488 100644
--- a/streampipes-messaging-mqtt/pom.xml
+++ b/streampipes-messaging-mqtt/pom.xml
@@ -20,7 +20,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -31,7 +31,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-messaging/pom.xml b/streampipes-messaging/pom.xml
index c688373..bc9af02 100644
--- a/streampipes-messaging/pom.xml
+++ b/streampipes-messaging/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
        <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,7 +32,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/streampipes-model-client/pom.xml b/streampipes-model-client/pom.xml
index 431bad4..391f540 100644
--- a/streampipes-model-client/pom.xml
+++ b/streampipes-model-client/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<groupId>org.apache.streampipes</groupId>
 		<artifactId>streampipes-parent</artifactId>
-		<version>0.70.0-SNAPSHOT</version>
+		<version>0.71.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>streampipes-model-client</artifactId>
@@ -32,12 +32,12 @@
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-commons</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-model-shared</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 
 		<!-- External dependencies -->
diff --git a/streampipes-model-shared/pom.xml b/streampipes-model-shared/pom.xml
index 11eb69b..ff90040 100644
--- a/streampipes-model-shared/pom.xml
+++ b/streampipes-model-shared/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/streampipes-model/pom.xml b/streampipes-model/pom.xml
index 53f9c6c..9230111 100644
--- a/streampipes-model/pom.xml
+++ b/streampipes-model/pom.xml
@@ -23,29 +23,29 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <dependencies>
         <!-- StreamPipes dependencies -->
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-commons</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-logging</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-vocabulary</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <!-- External dependencies -->
         <dependency>
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/MessageLd.java b/streampipes-model/src/main/java/org/apache/streampipes/model/MessageLd.java
deleted file mode 100644
index 61b3cd8..0000000
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/MessageLd.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.model;
-
-import org.apache.commons.lang3.RandomStringUtils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class MessageLd {
-
-	private static final String prefix = "urn:streampipes.org:spi:";
-
-	private String elementId;
-
-	private boolean success;
-
-	private String elementName;
-
-	private List<NotificationLd> notifications;
-
-	public MessageLd() {
-		this.elementId = prefix
-				+ this.getClass().getSimpleName().toLowerCase()
-				+ ":"
-				+ RandomStringUtils.randomAlphabetic(6);
-		this.elementName = "";
-	}
-
-	public MessageLd(MessageLd other) {
-		this();
-		this.success = other.isSuccess();
-		this.elementName = other.getElementName();
-		this.notifications = other.getNotifications();
-	}
-
-	public MessageLd(boolean success){
-		this();
-		this.success = success;
-		this.notifications = null;
-	}
-
-	public MessageLd(boolean success, List<NotificationLd> notifications) {
-		this();
-		this.success = success;
-		this.notifications = notifications;
-	}
-
-	public MessageLd(boolean success, List<NotificationLd> notifications, String elementName) {
-		this(success, notifications);
-		this.elementName = elementName;
-	}
-
-
-	public MessageLd(boolean success, NotificationLd...notifications) {
-		this();
-		this.success = success;
-		this.notifications = new ArrayList<>();
-		this.notifications.addAll(Arrays.asList(notifications));
-	}
-
-	public boolean isSuccess() {
-		return success;
-	}
-
-	public void setSuccess(boolean success) {
-		this.success = success;
-	}
-
-	public List<NotificationLd> getNotifications() {
-		return notifications;
-	}
-
-	public void setNotifications(List<NotificationLd> notifications) {
-		this.notifications = notifications;
-	}
-	
-	public boolean addNotification(NotificationLd notification)
-	{
-		return notifications.add(notification);
-	}
-
-	public String getElementName() {
-		return elementName;
-	}
-
-	public void setElementName(String elementName) {
-		this.elementName = elementName;
-	}
-
-	public String getElementId() {
-		return elementId;
-	}
-
-	public void setElementId(String elementId) {
-		this.elementId = elementId;
-	}
-	
-	
-}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/NotificationLd.java b/streampipes-model/src/main/java/org/apache/streampipes/model/NotificationLd.java
deleted file mode 100644
index 7b6b7b8..0000000
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/NotificationLd.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.model;
-
-import org.apache.commons.lang3.RandomStringUtils;
-
-public class NotificationLd {
-
-    private static final String prefix = "urn:streampipes.org:spi:";
-
-    private String elementId;
-
-    private String title;
-
-    private String description;
-
-    private String additionalInformation;
-
-    public NotificationLd() {
-        this.elementId = prefix
-                + this.getClass().getSimpleName().toLowerCase()
-                + ":"
-                + RandomStringUtils.randomAlphabetic(6);
-        this.additionalInformation = "";
-    }
-
-    public NotificationLd(NotificationLd other) {
-        this();
-        this.title = other.getTitle();
-        this.description = other.getDescription();
-        this.additionalInformation = other.getAdditionalInformation();
-    }
-
-    public NotificationLd(String title, String description) {
-        this();
-        this.title = title;
-        this.description = description;
-    }
-
-    public NotificationLd(String title, String description,
-                        String additionalInformation) {
-        this();
-        this.title = title;
-        this.description = description;
-        this.additionalInformation = additionalInformation;
-    }
-
-    public String getTitle() {
-        return title;
-    }
-
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public String getAdditionalInformation() {
-        return additionalInformation;
-    }
-
-    public void setAdditionalInformation(String additionalInformation) {
-        this.additionalInformation = additionalInformation;
-    }
-
-    public String getElementId() {
-        return elementId;
-    }
-
-    public void setElementId(String elementId) {
-        this.elementId = elementId;
-    }
-}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/StreamPipesErrorMessage.java b/streampipes-model/src/main/java/org/apache/streampipes/model/StreamPipesErrorMessage.java
new file mode 100644
index 0000000..c6bf711
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/StreamPipesErrorMessage.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model;
+
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.streampipes.model.shared.annotation.TsModel;
+
+@TsModel
+public class StreamPipesErrorMessage {
+
+  private String level;
+  private String title;
+  private String detail;
+
+  private String cause;
+  private String fullStackTrace;
+
+  public static StreamPipesErrorMessage from(Exception exception) {
+    String cause = exception.getCause() != null ? exception.getCause().getMessage() : exception.getMessage();
+    return new StreamPipesErrorMessage(
+      "error",
+      exception.getMessage(),
+      "",
+      ExceptionUtils.getStackTrace(exception),
+      cause);
+  }
+
+  public StreamPipesErrorMessage(String level,
+                                 String title,
+                                 String detail) {
+    this.level = level;
+    this.title = title;
+    this.detail = detail;
+  }
+
+  public StreamPipesErrorMessage(String level,
+                                 String title,
+                                 String detail,
+                                 String fullStackTrace,
+                                 String cause) {
+    this.level = level;
+    this.title = title;
+    this.detail = detail;
+    this.fullStackTrace = fullStackTrace;
+    this.cause = cause;
+  }
+
+  public String getLevel() {
+    return level;
+  }
+
+  public void setLevel(String level) {
+    this.level = level;
+  }
+
+  public String getTitle() {
+    return title;
+  }
+
+  public void setTitle(String title) {
+    this.title = title;
+  }
+
+  public String getDetail() {
+    return detail;
+  }
+
+  public void setDetail(String detail) {
+    this.detail = detail;
+  }
+
+  public String getFullStackTrace() {
+    return fullStackTrace;
+  }
+
+  public void setFullStackTrace(String fullStackTrace) {
+    this.fullStackTrace = fullStackTrace;
+  }
+
+  public String getCause() {
+    return cause;
+  }
+
+  public void setCause(String cause) {
+    this.cause = cause;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLink.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLink.java
new file mode 100644
index 0000000..74d15f0
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLink.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.assets;
+
+import java.util.Objects;
+
+public class AssetLink {
+
+  private String resourceId;
+  private String linkType;
+  private String linkLabel;
+  private String queryHint;
+  private boolean editingDisabled;
+
+  public AssetLink() {
+  }
+
+  public String getResourceId() {
+    return resourceId;
+  }
+
+  public void setResourceId(String resourceId) {
+    this.resourceId = resourceId;
+  }
+
+  public String getLinkType() {
+    return linkType;
+  }
+
+  public void setLinkType(String linkType) {
+    this.linkType = linkType;
+  }
+
+  public String getLinkLabel() {
+    return linkLabel;
+  }
+
+  public void setLinkLabel(String linkLabel) {
+    this.linkLabel = linkLabel;
+  }
+
+  public boolean isEditingDisabled() {
+    return editingDisabled;
+  }
+
+  public void setEditingDisabled(boolean editingDisabled) {
+    this.editingDisabled = editingDisabled;
+  }
+
+  public String getQueryHint() {
+    return queryHint;
+  }
+
+  public void setQueryHint(String queryHint) {
+    this.queryHint = queryHint;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    AssetLink assetLink = (AssetLink) o;
+    return resourceId.equals(assetLink.resourceId) && queryHint.equals(assetLink.queryHint);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(resourceId, queryHint);
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLinkType.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLinkType.java
new file mode 100644
index 0000000..79d6c26
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLinkType.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.assets;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AssetLinkType {
+
+  public final String appDocType = GenericDocTypes.DOC_ASSET_LINK_TYPE;
+
+  @JsonProperty("_id")
+  private @SerializedName("_id") String id;
+
+  private String linkType;
+  private String linkLabel;
+  private String linkColor;
+  private String linkIcon;
+  private String linkQueryHint;
+  private List<String> navPaths;
+  private boolean navigationActive;
+
+  public AssetLinkType(String linkType,
+                       String linkLabel,
+                       String linkColor,
+                       String linkIcon,
+                       String linkQueryHint,
+                       List<String> navPaths,
+                       boolean navigationActive) {
+    this.linkType = linkType;
+    this.linkLabel = linkLabel;
+    this.linkColor = linkColor;
+    this.linkIcon = linkIcon;
+    this.linkQueryHint = linkQueryHint;
+    this.navPaths = navPaths;
+    this.navigationActive = navigationActive;
+  }
+
+  public AssetLinkType() {
+    this.navPaths = new ArrayList<>();
+  }
+
+  public String getLinkType() {
+    return linkType;
+  }
+
+  public void setLinkType(String linkType) {
+    this.linkType = linkType;
+  }
+
+  public String getLinkLabel() {
+    return linkLabel;
+  }
+
+  public void setLinkLabel(String linkLabel) {
+    this.linkLabel = linkLabel;
+  }
+
+  public String getLinkColor() {
+    return linkColor;
+  }
+
+  public void setLinkColor(String linkColor) {
+    this.linkColor = linkColor;
+  }
+
+  public String getLinkIcon() {
+    return linkIcon;
+  }
+
+  public void setLinkIcon(String linkIcon) {
+    this.linkIcon = linkIcon;
+  }
+
+  public String getLinkQueryHint() {
+    return linkQueryHint;
+  }
+
+  public void setLinkQueryHint(String linkQueryHint) {
+    this.linkQueryHint = linkQueryHint;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getAppDocType() {
+    return appDocType;
+  }
+
+  public List<String> getNavPaths() {
+    return navPaths;
+  }
+
+  public void setNavPaths(List<String> navPaths) {
+    this.navPaths = navPaths;
+  }
+
+  public boolean isNavigationActive() {
+    return navigationActive;
+  }
+
+  public void setNavigationActive(boolean navigationActive) {
+    this.navigationActive = navigationActive;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetType.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetType.java
new file mode 100644
index 0000000..45b7151
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetType.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.assets;
+
+public class AssetType {
+
+  private String assetIcon;
+  private String assetIconColor;
+  private String assetTypeCategory;
+  private String assetTypeLabel;
+
+  public AssetType() {
+  }
+
+  public String getAssetIcon() {
+    return assetIcon;
+  }
+
+  public void setAssetIcon(String assetIcon) {
+    this.assetIcon = assetIcon;
+  }
+
+  public String getAssetIconColor() {
+    return assetIconColor;
+  }
+
+  public void setAssetIconColor(String assetIconColor) {
+    this.assetIconColor = assetIconColor;
+  }
+
+  public String getAssetTypeCategory() {
+    return assetTypeCategory;
+  }
+
+  public void setAssetTypeCategory(String assetTypeCategory) {
+    this.assetTypeCategory = assetTypeCategory;
+  }
+
+  public String getAssetTypeLabel() {
+    return assetTypeLabel;
+  }
+
+  public void setAssetTypeLabel(String assetTypeLabel) {
+    this.assetTypeLabel = assetTypeLabel;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAsset.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAsset.java
new file mode 100644
index 0000000..eeee4c6
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAsset.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.assets;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SpAsset {
+
+  private String assetId;
+  private String assetName;
+  private String assetDescription;
+
+  private AssetType assetType;
+  private List<AssetLink> assetLinks;
+
+  private List<SpAsset> assets;
+
+  public SpAsset() {
+    this.assets = new ArrayList<>();
+    this.assetLinks = new ArrayList<>();
+  }
+
+  public String getAssetId() {
+    return assetId;
+  }
+
+  public void setAssetId(String assetId) {
+    this.assetId = assetId;
+  }
+
+  public String getAssetName() {
+    return assetName;
+  }
+
+  public void setAssetName(String assetName) {
+    this.assetName = assetName;
+  }
+
+  public String getAssetDescription() {
+    return assetDescription;
+  }
+
+  public void setAssetDescription(String assetDescription) {
+    this.assetDescription = assetDescription;
+  }
+
+  public AssetType getAssetType() {
+    return assetType;
+  }
+
+  public void setAssetType(AssetType assetType) {
+    this.assetType = assetType;
+  }
+
+  public List<AssetLink> getAssetLinks() {
+    return assetLinks;
+  }
+
+  public void setAssetLinks(List<AssetLink> assetLinks) {
+    this.assetLinks = assetLinks;
+  }
+
+  public List<SpAsset> getAssets() {
+    return assets;
+  }
+
+  public void setAssets(List<SpAsset> assets) {
+    this.assets = assets;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAssetModel.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAssetModel.java
new file mode 100644
index 0000000..99787aa
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAssetModel.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.assets;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+
+public class SpAssetModel extends SpAsset {
+
+  public static final String appDocType = GenericDocTypes.DOC_ASSET_MANGEMENT;
+
+  @JsonProperty("_id")
+  private @SerializedName("_id") String id;
+
+  private boolean removable;
+
+  public SpAssetModel() {
+    super();
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public boolean isRemovable() {
+    return removable;
+  }
+
+  public void setRemovable(boolean removable) {
+    this.removable = removable;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/AdapterDescription.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/AdapterDescription.java
index 5647f3f..173f2e1 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/AdapterDescription.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/AdapterDescription.java
@@ -23,6 +23,7 @@
 import org.apache.streampipes.model.connect.rules.TransformationRuleDescription;
 import org.apache.streampipes.model.connect.rules.schema.SchemaTransformationRuleDescription;
 import org.apache.streampipes.model.connect.rules.stream.StreamTransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription;
 import org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription;
 import org.apache.streampipes.model.grounding.*;
 import org.apache.streampipes.model.shared.annotation.TsModel;
@@ -162,17 +163,18 @@
         this.adapterType = adapterType;
     }
 
-    public List getValueRules() {
-        List tmp = new ArrayList<>();
+    public List<TransformationRuleDescription> getValueRules() {
+        var tmp = new ArrayList<TransformationRuleDescription>();
         rules.forEach(rule -> {
-            if(rule instanceof ValueTransformationRuleDescription)
+            if(rule instanceof ValueTransformationRuleDescription && !(rule instanceof AddTimestampRuleDescription)) {
                 tmp.add(rule);
+            }
         });
         return tmp;
     }
 
-    public List getStreamRules() {
-        List tmp = new ArrayList<>();
+    public List<TransformationRuleDescription> getStreamRules() {
+        var tmp = new ArrayList<TransformationRuleDescription>();
         rules.forEach(rule -> {
             if(rule instanceof StreamTransformationRuleDescription)
                 tmp.add(rule);
@@ -180,8 +182,8 @@
         return tmp;
     }
 
-    public List getSchemaRules() {
-        List tmp = new ArrayList<>();
+    public List<TransformationRuleDescription> getSchemaRules() {
+        var tmp = new ArrayList<TransformationRuleDescription>();
         rules.forEach(rule -> {
             if(rule instanceof SchemaTransformationRuleDescription)
                 tmp.add(rule);
@@ -231,10 +233,19 @@
         this.selectedEndpointUrl = selectedEndpointUrl;
     }
 
+    /**
+     * @deprecated check if the service group can be removed as a single pipeline element
+     * can correspond to different service groups
+     */
+    @Deprecated
     public String getCorrespondingServiceGroup() {
         return correspondingServiceGroup;
     }
 
+    /**
+     * @deprecated check if the service group can be removed as a single pipeline element
+     * can correspond to different service groups
+     */
     public void setCorrespondingServiceGroup(String correspondingServiceGroup) {
         this.correspondingServiceGroup = correspondingServiceGroup;
     }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/AdapterEventPreview.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/AdapterEventPreview.java
new file mode 100644
index 0000000..d70af4f
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/AdapterEventPreview.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.guess;
+
+import org.apache.streampipes.model.connect.rules.TransformationRuleDescription;
+import org.apache.streampipes.model.shared.annotation.TsModel;
+
+import java.util.List;
+import java.util.Map;
+
+@TsModel
+public class AdapterEventPreview {
+
+  private List<TransformationRuleDescription> rules;
+
+  private Map<String, GuessTypeInfo> inputData;
+
+  public List<TransformationRuleDescription> getRules() {
+    return rules;
+  }
+
+  public void setRules(List<TransformationRuleDescription> rules) {
+    this.rules = rules;
+  }
+
+  public Map<String, GuessTypeInfo> getInputData() {
+    return inputData;
+  }
+
+  public void setInputData(Map<String, GuessTypeInfo> inputData) {
+    this.inputData = inputData;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/AdapterGuessInfo.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/AdapterGuessInfo.java
new file mode 100644
index 0000000..6aa137f
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/AdapterGuessInfo.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.guess;
+
+import org.apache.streampipes.model.schema.EventSchema;
+
+import java.util.List;
+import java.util.Map;
+
+public class AdapterGuessInfo {
+
+  private EventSchema eventSchema;
+  private List<Map<String, GuessTypeInfo>> eventPreview;
+
+  public AdapterGuessInfo() {
+  }
+
+  public AdapterGuessInfo(EventSchema eventSchema,
+                          Map<String, GuessTypeInfo> singleEventSample) {
+    this.eventSchema = eventSchema;
+    this.eventPreview = List.of(singleEventSample);
+  }
+
+  public EventSchema getEventSchema() {
+    return eventSchema;
+  }
+
+  public void setEventSchema(EventSchema eventSchema) {
+    this.eventSchema = eventSchema;
+  }
+
+  public List<Map<String, GuessTypeInfo>> getEventPreview() {
+    return eventPreview;
+  }
+
+  public void setEventPreview(List<Map<String, GuessTypeInfo>> eventPreview) {
+    this.eventPreview = eventPreview;
+  }
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatus.java
similarity index 87%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatus.java
index 58ba04b..eec688b 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatus.java
@@ -16,3 +16,10 @@
  *
  */
 
+package org.apache.streampipes.model.connect.guess;
+
+public enum FieldStatus {
+  GOOD,
+  BAD,
+  ATTENTION
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatusInfo.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatusInfo.java
new file mode 100644
index 0000000..a66b83d
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatusInfo.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.guess;
+
+public class FieldStatusInfo {
+
+  private FieldStatus fieldStatus;
+  private String additionalInfo;
+  private boolean changesRequired;
+
+  public static FieldStatusInfo good() {
+    var info = new FieldStatusInfo();
+    info.setFieldStatus(FieldStatus.GOOD);
+    return info;
+  }
+
+  public static FieldStatusInfo bad(String additionalInfo,
+                                    boolean changesRequired) {
+    var info = new FieldStatusInfo();
+    info.setFieldStatus(FieldStatus.BAD);
+    info.setAdditionalInfo(additionalInfo);
+    info.setChangesRequired(changesRequired);
+
+    return info;
+  }
+
+  public FieldStatusInfo() {
+  }
+
+  public FieldStatus getFieldStatus() {
+    return fieldStatus;
+  }
+
+  public void setFieldStatus(FieldStatus fieldStatus) {
+    this.fieldStatus = fieldStatus;
+  }
+
+  public String getAdditionalInfo() {
+    return additionalInfo;
+  }
+
+  public void setAdditionalInfo(String additionalInfo) {
+    this.additionalInfo = additionalInfo;
+  }
+
+  public boolean isChangesRequired() {
+    return changesRequired;
+  }
+
+  public void setChangesRequired(boolean changesRequired) {
+    this.changesRequired = changesRequired;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessSchema.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessSchema.java
index 4bda9da..ba39f89 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessSchema.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessSchema.java
@@ -22,18 +22,31 @@
 import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.model.shared.annotation.TsModel;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 @TsModel
 public class GuessSchema extends UnnamedStreamPipesEntity {
 
     public EventSchema eventSchema;
 
+    public List<Map<String, GuessTypeInfo>> eventPreview;
+
+    public Map<String, FieldStatusInfo> fieldStatusInfo;
+
     public GuessSchema() {
         super();
+        this.eventPreview = new ArrayList<>();
+        this.fieldStatusInfo = new HashMap<>();
     }
 
     public GuessSchema(GuessSchema other) {
         super(other);
         this.eventSchema = other.getEventSchema() != null ? new EventSchema(other.getEventSchema()) : null;
+        this.eventPreview = other.getEventPreview();
+        this.fieldStatusInfo = other.getFieldStatusInfo();
     }
     public EventSchema getEventSchema() {
         return eventSchema;
@@ -43,4 +56,21 @@
         this.eventSchema = eventSchema;
     }
 
+    public List<Map<String, GuessTypeInfo>> getEventPreview() {
+        return eventPreview;
+    }
+
+    public void setEventPreview(List<Map<String, GuessTypeInfo>> eventPreview) {
+        this.eventPreview = eventPreview;
+    }
+
+    public Map<String, FieldStatusInfo> getFieldStatusInfo() {
+        return fieldStatusInfo;
+    }
+
+    public void setFieldStatusInfo(Map<String, FieldStatusInfo> fieldStatusInfo) {
+        this.fieldStatusInfo = fieldStatusInfo;
+    }
+
+
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessTypeInfo.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessTypeInfo.java
new file mode 100644
index 0000000..7404451
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessTypeInfo.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.guess;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+public class GuessTypeInfo {
+
+  private String type;
+
+  @JsonTypeInfo(use = JsonTypeInfo.Id.NONE, property = "type")
+  private Object value;
+
+  public GuessTypeInfo() {
+  }
+
+  public GuessTypeInfo(String type, Object value) {
+    this.type = type;
+    this.value = value;
+  }
+
+  public String getType() {
+    return type;
+  }
+
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  public Object getValue() {
+    return value;
+  }
+
+  public void setValue(Object value) {
+    this.value = value;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRuleDescription.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRuleDescription.java
index bd1b85b..590b416 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRuleDescription.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRuleDescription.java
@@ -41,6 +41,7 @@
         @JsonSubTypes.Type(DeleteRuleDescription.class),
         @JsonSubTypes.Type(RenameRuleDescription.class),
         @JsonSubTypes.Type(MoveRuleDescription.class),
+        @JsonSubTypes.Type(ChangeDatatypeTransformationRuleDescription.class),
         @JsonSubTypes.Type(CorrectionValueTransformationRuleDescription.class),
 })
 public abstract class TransformationRuleDescription extends UnnamedStreamPipesEntity {
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/ChangeDatatypeTransformationRuleDescription.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/ChangeDatatypeTransformationRuleDescription.java
new file mode 100644
index 0000000..aa64e64
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/ChangeDatatypeTransformationRuleDescription.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.rules.value;
+
+public class ChangeDatatypeTransformationRuleDescription extends ValueTransformationRuleDescription {
+
+  private String runtimeKey;
+  private String originalDatatypeXsd;
+  private String targetDatatypeXsd;
+
+  public ChangeDatatypeTransformationRuleDescription() {
+  }
+
+  public ChangeDatatypeTransformationRuleDescription(ChangeDatatypeTransformationRuleDescription other) {
+    super(other);
+    this.runtimeKey = other.getRuntimeKey();
+    this.originalDatatypeXsd = other.getOriginalDatatypeXsd();
+    this.targetDatatypeXsd = other.getTargetDatatypeXsd();
+  }
+
+  public String getRuntimeKey() {
+    return runtimeKey;
+  }
+
+  public void setRuntimeKey(String runtimeKey) {
+    this.runtimeKey = runtimeKey;
+  }
+
+  public String getOriginalDatatypeXsd() {
+    return originalDatatypeXsd;
+  }
+
+  public void setOriginalDatatypeXsd(String originalDatatypeXsd) {
+    this.originalDatatypeXsd = originalDatatypeXsd;
+  }
+
+  public String getTargetDatatypeXsd() {
+    return targetDatatypeXsd;
+  }
+
+  public void setTargetDatatypeXsd(String targetDatatypeXsd) {
+    this.targetDatatypeXsd = targetDatatypeXsd;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataLakeMeasure.java b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataLakeMeasure.java
index 532e537..5b90fd9 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataLakeMeasure.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataLakeMeasure.java
@@ -18,6 +18,8 @@
 
 package org.apache.streampipes.model.datalake;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
 import org.apache.streampipes.model.base.UnnamedStreamPipesEntity;
 import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.model.shared.annotation.TsModel;
@@ -25,12 +27,21 @@
 @TsModel
 public class DataLakeMeasure extends UnnamedStreamPipesEntity {
 
+    public final static String CURRENT_SCHEMA_VERSION = "1.1";
+
+    @JsonProperty("_rev")
+    private @SerializedName("_rev") String rev;
+
     private String measureName;
+
+    private String timestampField;
     private EventSchema eventSchema;
     private String pipelineId;
     private String pipelineName;
     private boolean pipelineIsRunning;
 
+    private String schemaVersion;
+
     public DataLakeMeasure() {
         super();
     }
@@ -47,6 +58,12 @@
         this.eventSchema = eventSchema;
     }
 
+    public DataLakeMeasure(String measureName, String timestampField, EventSchema eventSchema) {
+        this.measureName = measureName;
+        this.eventSchema = eventSchema;
+        this.timestampField = timestampField;
+    }
+
     public String getMeasureName() {
         return measureName;
     }
@@ -86,4 +103,28 @@
     public void setPipelineIsRunning(boolean pipelineIsRunning) {
         this.pipelineIsRunning = pipelineIsRunning;
     }
+
+    public String getSchemaVersion() {
+        return schemaVersion;
+    }
+
+    public void setSchemaVersion(String schemaVersion) {
+        this.schemaVersion = schemaVersion;
+    }
+
+    public String getTimestampField() {
+        return timestampField;
+    }
+
+    public void setTimestampField(String timestampField) {
+        this.timestampField = timestampField;
+    }
+
+    public String getRev() {
+        return rev;
+    }
+
+    public void setRev(String rev) {
+        this.rev = rev;
+    }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/SpQueryResult.java b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/SpQueryResult.java
index 8a2a54c..c3c9ef7 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/SpQueryResult.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/SpQueryResult.java
@@ -31,6 +31,7 @@
     private List<DataSeries> allDataSeries;
     private int sourceIndex;
     private SpQueryStatus spQueryStatus;
+    private String forId;
 
     public SpQueryResult() {
         this.total = 0;
@@ -92,4 +93,12 @@
     public void setSpQueryStatus(SpQueryStatus spQueryStatus) {
         this.spQueryStatus = spQueryStatus;
     }
+
+    public String getForId() {
+        return forId;
+    }
+
+    public void setForId(String forId) {
+        this.forId = forId;
+    }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/export/AssetExportConfiguration.java b/streampipes-model/src/main/java/org/apache/streampipes/model/export/AssetExportConfiguration.java
new file mode 100644
index 0000000..bd1e946
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/export/AssetExportConfiguration.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.export;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class AssetExportConfiguration {
+
+  private String assetId;
+  private String assetName;
+
+  private Set<ExportItem> assets;
+  private Set<ExportItem> adapters;
+  private Set<ExportItem> dashboards;
+  private Set<ExportItem> dataViews;
+  private Set<ExportItem> dataLakeMeasures;
+  private Set<ExportItem> dataSources;
+  private Set<ExportItem> pipelines;
+  private Set<ExportItem> files;
+
+  private boolean overrideBrokerSettings;
+
+  public AssetExportConfiguration() {
+    this.adapters = new HashSet<>();
+    this.dashboards = new HashSet<>();
+    this.dataViews = new HashSet<>();
+    this.dataLakeMeasures = new HashSet<>();
+    this.dataSources = new HashSet<>();
+    this.pipelines = new HashSet<>();
+    this.files = new HashSet<>();
+    this.assets = new HashSet<>();
+  }
+
+  public Set<ExportItem> getAdapters() {
+    return adapters;
+  }
+
+  public void setAdapters(Set<ExportItem> adapters) {
+    this.adapters = adapters;
+  }
+
+  public void addAdapter(ExportItem item) {
+    this.adapters.add(item);
+  }
+
+  public Set<ExportItem> getDashboards() {
+    return dashboards;
+  }
+
+  public void setDashboards(Set<ExportItem> dashboards) {
+    this.dashboards = dashboards;
+  }
+
+  public void addDashboard(ExportItem item) {
+    this.dashboards.add(item);
+  }
+
+  public Set<ExportItem> getDataViews() {
+    return dataViews;
+  }
+
+  public void setDataViews(Set<ExportItem> dataViews) {
+    this.dataViews = dataViews;
+  }
+
+  public void addDataView(ExportItem item) {
+    this.dataViews.add(item);
+  }
+
+  public Set<ExportItem> getDataLakeMeasures() {
+    return dataLakeMeasures;
+  }
+
+  public void setDataLakeMeasures(Set<ExportItem> dataLakeMeasures) {
+    this.dataLakeMeasures = dataLakeMeasures;
+  }
+
+  public void addDataLakeMeasure(ExportItem item) {
+    this.dataLakeMeasures.add(item);
+  }
+
+  public Set<ExportItem> getDataSources() {
+    return dataSources;
+  }
+
+  public void setDataSources(Set<ExportItem> dataSources) {
+    this.dataSources = dataSources;
+  }
+
+  public void addDataSource(ExportItem item) {
+    this.dataSources.add(item);
+  }
+
+  public String getAssetId() {
+    return assetId;
+  }
+
+  public void setAssetId(String assetId) {
+    this.assetId = assetId;
+  }
+
+  public Set<ExportItem> getPipelines() {
+    return pipelines;
+  }
+
+  public void setPipelines(Set<ExportItem> pipelines) {
+    this.pipelines = pipelines;
+  }
+
+  public void addPipeline(ExportItem item) {
+    this.pipelines.add(item);
+  }
+
+  public Set<ExportItem> getFiles() {
+    return files;
+  }
+
+  public void setFiles(Set<ExportItem> files) {
+    this.files = files;
+  }
+
+  public void addFile(ExportItem item) {
+    this.files.add(item);
+  }
+
+  public String getAssetName() {
+    return assetName;
+  }
+
+  public void setAssetName(String assetName) {
+    this.assetName = assetName;
+  }
+
+  public Set<ExportItem> getAssets() {
+    return assets;
+  }
+
+  public void setAssets(Set<ExportItem> assets) {
+    this.assets = assets;
+  }
+
+  public void addAsset(ExportItem asset) {
+    this.assets.add(asset);
+  }
+
+  public boolean isOverrideBrokerSettings() {
+    return overrideBrokerSettings;
+  }
+
+  public void setOverrideBrokerSettings(boolean overrideBrokerSettings) {
+    this.overrideBrokerSettings = overrideBrokerSettings;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/export/ExportConfiguration.java b/streampipes-model/src/main/java/org/apache/streampipes/model/export/ExportConfiguration.java
new file mode 100644
index 0000000..2a0052b
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/export/ExportConfiguration.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.streampipes.model.export;
+
+import org.apache.streampipes.model.shared.annotation.TsModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@TsModel
+public class ExportConfiguration {
+
+  private List<AssetExportConfiguration> assetExportConfiguration;
+
+  public ExportConfiguration() {
+    this.assetExportConfiguration = new ArrayList<>();
+  }
+
+  public List<AssetExportConfiguration> getAssetExportConfiguration() {
+    return assetExportConfiguration;
+  }
+
+  public void setAssetExportConfiguration(List<AssetExportConfiguration> assetExportConfiguration) {
+    this.assetExportConfiguration = assetExportConfiguration;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/export/ExportItem.java b/streampipes-model/src/main/java/org/apache/streampipes/model/export/ExportItem.java
new file mode 100644
index 0000000..cb62711
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/export/ExportItem.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.export;
+
+public class ExportItem {
+
+  private String resourceId;
+  private String label;
+  private boolean selected;
+
+  public ExportItem() {
+  }
+
+  public ExportItem(String resourceId, String label, boolean selected) {
+    this.resourceId = resourceId;
+    this.label = label;
+    this.selected = selected;
+  }
+
+  public String getResourceId() {
+    return resourceId;
+  }
+
+  public void setResourceId(String resourceId) {
+    this.resourceId = resourceId;
+  }
+
+  public String getLabel() {
+    return label;
+  }
+
+  public void setLabel(String label) {
+    this.label = label;
+  }
+
+  public boolean isSelected() {
+    return selected;
+  }
+
+  public void setSelected(boolean selected) {
+    this.selected = selected;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/export/StreamPipesApplicationPackage.java b/streampipes-model/src/main/java/org/apache/streampipes/model/export/StreamPipesApplicationPackage.java
new file mode 100644
index 0000000..a95dc63
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/export/StreamPipesApplicationPackage.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.export;
+
+import org.apache.streampipes.model.shared.annotation.TsModel;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@TsModel
+public class StreamPipesApplicationPackage {
+
+  private Set<String> requiredProcessorAppIds;
+  private Set<String> requiredDataSinkAppIds;
+  private Set<String> requiredAdapterAppIds;
+
+  private Set<String> assets;
+  private Set<String> adapters;
+  private Set<String> dashboards;
+  private Set<String> dashboardWidgets;
+  private Set<String> dataViews;
+  private Set<String> dataViewWidgets;
+  private Set<String> dataLakeMeasures;
+  private Set<String> dataSources;
+  private Set<String> pipelines;
+  private Set<String> files;
+
+  public StreamPipesApplicationPackage() {
+    this.requiredProcessorAppIds = new HashSet<>();
+    this.requiredDataSinkAppIds = new HashSet<>();
+    this.requiredAdapterAppIds = new HashSet<>();
+
+    this.adapters = new HashSet<>();
+    this.assets = new HashSet<>();
+    this.dashboards = new HashSet<>();
+    this.dashboardWidgets = new HashSet<>();
+    this.dataViews = new HashSet<>();
+    this.dataViewWidgets = new HashSet<>();
+    this.dataLakeMeasures = new HashSet<>();
+    this.dataSources = new HashSet<>();
+    this.pipelines = new HashSet<>();
+    this.files = new HashSet<>();
+  }
+
+  public Set<String> getRequiredProcessorAppIds() {
+    return requiredProcessorAppIds;
+  }
+
+  public void setRequiredProcessorAppIds(Set<String> requiredProcessorAppIds) {
+    this.requiredProcessorAppIds = requiredProcessorAppIds;
+  }
+
+  public Set<String> getRequiredDataSinkAppIds() {
+    return requiredDataSinkAppIds;
+  }
+
+  public void setRequiredDataSinkAppIds(Set<String> requiredDataSinkAppIds) {
+    this.requiredDataSinkAppIds = requiredDataSinkAppIds;
+  }
+
+  public Set<String> getRequiredAdapterAppIds() {
+    return requiredAdapterAppIds;
+  }
+
+  public void setRequiredAdapterAppIds(Set<String> requiredAdapterAppIds) {
+    this.requiredAdapterAppIds = requiredAdapterAppIds;
+  }
+
+  public Set<String> getAdapters() {
+    return adapters;
+  }
+
+  public void setAdapters(Set<String> adapters) {
+    this.adapters = adapters;
+  }
+
+  public void addAdapter(String adapter) {
+    this.adapters.add(adapter);
+  }
+
+  public Set<String> getDashboards() {
+    return dashboards;
+  }
+
+  public void setDashboards(Set<String> dashboards) {
+    this.dashboards = dashboards;
+  }
+
+  public void addDashboard(String dashboard) {
+    this.dashboards.add(dashboard);
+  }
+
+  public Set<String> getDashboardWidgets() {
+    return dashboardWidgets;
+  }
+
+  public void setDashboardWidgets(Set<String> dashboardWidgets) {
+    this.dashboardWidgets = dashboardWidgets;
+  }
+
+  public void addDashboardWidget(String dashboardWidget) {
+    this.dashboardWidgets.add(dashboardWidget);
+  }
+
+  public Set<String> getDataViews() {
+    return dataViews;
+  }
+
+  public void setDataViews(Set<String> dataViews) {
+    this.dataViews = dataViews;
+  }
+
+  public void addDataView(String dataView) {
+    this.dataViews.add(dataView);
+  }
+
+  public Set<String> getDataViewWidgets() {
+    return dataViewWidgets;
+  }
+
+  public void setDataViewWidgets(Set<String> dataViewWidgets) {
+    this.dataViewWidgets = dataViewWidgets;
+  }
+
+  public void addDataViewWidget(String dataViewWidget) {
+    this.dataViewWidgets.add(dataViewWidget);
+  }
+
+  public Set<String> getDataLakeMeasures() {
+    return dataLakeMeasures;
+  }
+
+  public void setDataLakeMeasures(Set<String> dataLakeMeasures) {
+    this.dataLakeMeasures = dataLakeMeasures;
+  }
+
+  public void addDataLakeMeasure(String dataLakeMeasure) {
+    this.dataLakeMeasures.add(dataLakeMeasure);
+  }
+
+  public Set<String> getDataSources() {
+    return dataSources;
+  }
+
+  public void setDataSources(Set<String> dataSources) {
+    this.dataSources = dataSources;
+  }
+
+  public void addDataSource(String dataSource) {
+    this.dataSources.add(dataSource);
+  }
+
+  public Set<String> getPipelines() {
+    return pipelines;
+  }
+
+  public void setPipelines(Set<String> pipelines) {
+    this.pipelines = pipelines;
+  }
+
+  public void addPipeline(String pipeline) {
+    this.pipelines.add(pipeline);
+  }
+
+  public Set<String> getFiles() {
+    return files;
+  }
+
+  public void setFiles(Set<String> files) {
+    this.files = files;
+  }
+
+  public void addFile(String file) {
+    this.files.add(file);
+  }
+
+  public Set<String> getAssets() {
+    return assets;
+  }
+
+  public void setAssets(Set<String> assets) {
+    this.assets = assets;
+  }
+
+  public void addAsset(String asset) {
+    this.assets.add(asset);
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/runtime/Event.java b/streampipes-model/src/main/java/org/apache/streampipes/model/runtime/Event.java
index 23143fe..84fd010 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/runtime/Event.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/runtime/Event.java
@@ -17,6 +17,7 @@
  */
 package org.apache.streampipes.model.runtime;
 
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.model.constants.PropertySelectorConstants;
 import org.apache.streampipes.model.runtime.field.AbstractField;
 import org.apache.streampipes.model.runtime.field.PrimitiveField;
@@ -71,7 +72,7 @@
             .map(Map.Entry::getValue)
             .filter(entry -> entry.getFieldNameIn().equals(runtimeName))
             .findFirst()
-            .orElseThrow(() -> new IllegalArgumentException("Field " + runtimeName + " not found"));
+            .orElseThrow(() -> new SpRuntimeException("Field " + runtimeName + " not found"));
   }
 
   public void removeFieldBySelector(String fieldSelector) {
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/template/PipelineTemplateDescription.java b/streampipes-model/src/main/java/org/apache/streampipes/model/template/PipelineTemplateDescription.java
index 81f46b4..52fa8f3 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/template/PipelineTemplateDescription.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/template/PipelineTemplateDescription.java
@@ -28,15 +28,6 @@
 @TsModel
 public class PipelineTemplateDescription extends NamedStreamPipesEntity {
 
-  //@RdfProperty(RDFS.LABEL)
-  //private String pipelineTemplateName;
-
-  //@RdfProperty(StreamPipes.INTERNAL_NAME)
-  //private String pipelineTemplateId;
-
-  //@RdfProperty(RDFS.DESCRIPTION)
-  //private String pipelineTemplateDescription;
-
   private List<BoundPipelineElement> boundTo;
 
   public PipelineTemplateDescription() {
diff --git a/streampipes-performance-tests/pom.xml b/streampipes-performance-tests/pom.xml
index 36cb506..c31a013 100644
--- a/streampipes-performance-tests/pom.xml
+++ b/streampipes-performance-tests/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,22 +32,22 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-kafka</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-pipeline-management/pom.xml b/streampipes-pipeline-management/pom.xml
index 19af5ba..e40e532 100644
--- a/streampipes-pipeline-management/pom.xml
+++ b/streampipes-pipeline-management/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>streampipes-pipeline-management</artifactId>
@@ -30,87 +30,87 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-commons</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-cbor</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-fst</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-smile</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-jms</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-mqtt</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-kafka</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-resource-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-serializers-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-discovery</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-user-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <!-- External dependencies -->
         <dependency>
@@ -135,13 +135,13 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-measurement-units</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-test-utils</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/execution/endpoint/ExtensionsServiceEndpointGenerator.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/execution/endpoint/ExtensionsServiceEndpointGenerator.java
index b3feb3b..8d430e4 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/execution/endpoint/ExtensionsServiceEndpointGenerator.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/execution/endpoint/ExtensionsServiceEndpointGenerator.java
@@ -65,7 +65,7 @@
       return getServiceEndpoints().get(0);
     } else {
       LOG.error("Could not find any service endpoints for appId {}, serviceTag {}", appId, this.spServiceUrlProvider.getServiceTag(appId).asString());
-      throw new NoServiceEndpointsAvailableException("Could not find any matching service endpoints");
+      throw new NoServiceEndpointsAvailableException("Could not find any matching service endpoints - are all software components running?");
     }
   }
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
index 7a89ddc..f204ab2 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
@@ -18,6 +18,8 @@
 
 package org.apache.streampipes.manager.setup;
 
+import org.apache.streampipes.manager.setup.tasks.CreateAssetLinkTypeTask;
+import org.apache.streampipes.manager.setup.tasks.CreateDefaultAssetTask;
 import org.apache.streampipes.model.client.endpoint.ExtensionsServiceEndpoint;
 import org.apache.streampipes.storage.couchdb.impl.ExtensionsServiceEndpointStorageImpl;
 import org.apache.streampipes.storage.couchdb.utils.Utils;
@@ -44,6 +46,8 @@
     createDatabases();
     createViews();
     addRdfEndpoints();
+    new CreateAssetLinkTypeTask().execute();
+    new CreateDefaultAssetTask().execute();
   }
 
   @Override
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateAssetLinkTypeTask.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateAssetLinkTypeTask.java
new file mode 100644
index 0000000..90ddc2d
--- /dev/null
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateAssetLinkTypeTask.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.manager.setup.tasks;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.commons.random.UUIDGenerator;
+import org.apache.streampipes.model.assets.AssetLinkType;
+import org.apache.streampipes.storage.api.IGenericStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+public class CreateAssetLinkTypeTask implements InstallationTask {
+
+  private List<AssetLinkType> defaultLinkTypes = Arrays.asList(
+    new AssetLinkType("data-view", "Data View", "var(--color-data-view)", "search", "data-view", List.of("dataexplorer"), true),
+    new AssetLinkType("dashboard", "Dashboard", "var(--color-dashboard)", "insert_chart", "dashboard", List.of("dashboard"), true),
+    new AssetLinkType("adapter", "Adapter", "var(--color-adapter)", "power", "adapter", List.of("connect"), true),
+    new AssetLinkType("data-source", "Data Source", "var(--color-data-source)", "dataset", "data-source", List.of(), false),
+    new AssetLinkType("pipeline", "Pipeline", "var(--color-pipeline)", "play_arrow", "pipeline", List.of("pipeline", "details"), true),
+    new AssetLinkType("measurement", "Data Lake Storage", "var(--color-measurement)", "folder", "measurement", List.of(), false),
+    new AssetLinkType("file", "File", "var(--color-file)", "draft", "file", List.of(), false)
+  );
+
+  @Override
+  public void execute() {
+    var genericStorage = getGenericStorage();
+
+    this.defaultLinkTypes.forEach(link -> {
+      try {
+        link.setId(UUIDGenerator.generateUuid());
+        genericStorage.create(link, AssetLinkType.class);
+      } catch (IOException e) {
+        e.printStackTrace();
+        throw new SpRuntimeException("Could not create asset link document");
+      }
+    });
+  }
+
+  private IGenericStorage getGenericStorage() {
+    return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage();
+  }
+}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateDefaultAssetTask.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateDefaultAssetTask.java
new file mode 100644
index 0000000..9293592
--- /dev/null
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateDefaultAssetTask.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.manager.setup.tasks;
+
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+import org.apache.streampipes.model.assets.SpAssetModel;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+
+public class CreateDefaultAssetTask implements InstallationTask {
+
+  @Override
+  public void execute() {
+    var asset = new SpAssetModel();
+    asset.setId(GenericDocTypes.DEFAULT_ASSET_DOC_ID);
+    asset.setAssetId("default-asset");
+    asset.setAssetName("Default Asset");
+    asset.setRemovable(true);
+
+    try {
+      StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().create(asset, SpAssetModel.class);
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/InstallationTask.java
similarity index 87%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/InstallationTask.java
index 58ba04b..39ec0f1 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/InstallationTask.java
@@ -16,3 +16,9 @@
  *
  */
 
+package org.apache.streampipes.manager.setup.tasks;
+
+public interface InstallationTask {
+
+  void execute();
+}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/AbstractTemplateHandler.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/AbstractTemplateHandler.java
new file mode 100644
index 0000000..b53ba70
--- /dev/null
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/AbstractTemplateHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.manager.template;
+
+import org.apache.streampipes.model.template.PipelineElementTemplate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class AbstractTemplateHandler<T> {
+
+  protected T element;
+  protected PipelineElementTemplate template;
+
+  protected boolean overwriteNameAndDescription;
+
+  public AbstractTemplateHandler(PipelineElementTemplate template,
+                                 T element,
+                                 boolean overwriteNameAndDescription) {
+    this.template = template;
+    this.element = element;
+    this.overwriteNameAndDescription = overwriteNameAndDescription;
+  }
+
+  public T applyTemplateOnPipelineElement() {
+    Map<String, Object> configs = new HashMap<>();
+    template.getTemplateConfigs().forEach((key, value) -> configs.put(key, value.getValue()));
+    PipelineElementTemplateVisitor visitor = new PipelineElementTemplateVisitor(configs);
+    visitStaticProperties(visitor);
+
+    if (overwriteNameAndDescription) {
+      applyNameAndDescription(template.getTemplateName(), template.getTemplateDescription());
+    }
+
+    return element;
+  }
+
+  protected abstract void visitStaticProperties(PipelineElementTemplateVisitor visitor);
+
+  protected abstract void applyNameAndDescription(String name, String description);
+}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/AdapterTemplateHandler.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/AdapterTemplateHandler.java
new file mode 100644
index 0000000..c3aa7d3
--- /dev/null
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/AdapterTemplateHandler.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.manager.template;
+
+import org.apache.streampipes.model.connect.adapter.*;
+import org.apache.streampipes.model.template.PipelineElementTemplate;
+
+public class AdapterTemplateHandler extends AbstractTemplateHandler<AdapterDescription> {
+
+  public AdapterTemplateHandler(PipelineElementTemplate template,
+                                        AdapterDescription adapterDescription,
+                                        boolean overwriteNameAndDescription) {
+    super(template, adapterDescription, overwriteNameAndDescription);
+  }
+
+  @Override
+  protected void visitStaticProperties(PipelineElementTemplateVisitor visitor) {
+    if (element instanceof SpecificAdapterStreamDescription || element instanceof SpecificAdapterSetDescription) {
+      element.getConfig().forEach(config -> config.accept(visitor));
+    } else if (element instanceof GenericAdapterSetDescription || element instanceof GenericAdapterStreamDescription) {
+      ((GenericAdapterDescription) element).getProtocolDescription().getConfig().forEach(config -> config.accept(visitor));
+    }
+  }
+
+  @Override
+  protected void applyNameAndDescription(String name, String description) {
+    element.setName(name);
+    element.setDescription(description);
+  }
+}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateHandler.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateHandler.java
index 97881fa..1269f35 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateHandler.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateHandler.java
@@ -20,35 +20,22 @@
 import org.apache.streampipes.model.base.InvocableStreamPipesEntity;
 import org.apache.streampipes.model.template.PipelineElementTemplate;
 
-import java.util.HashMap;
-import java.util.Map;
-
-public abstract class PipelineElementTemplateHandler<T extends InvocableStreamPipesEntity> {
-
-  protected T pipelineElement;
-  protected PipelineElementTemplate template;
-
-  private boolean overwriteNameAndDescription;
+public abstract class PipelineElementTemplateHandler<T extends InvocableStreamPipesEntity> extends AbstractTemplateHandler<T> {
 
   public PipelineElementTemplateHandler(PipelineElementTemplate template,
                                         T pipelineElement,
                                         boolean overwriteNameAndDescription) {
-    this.template = template;
-    this.pipelineElement = pipelineElement;
-    this.overwriteNameAndDescription = overwriteNameAndDescription;
+    super(template, pipelineElement, overwriteNameAndDescription);
   }
 
-  public T applyTemplateOnPipelineElement() {
-      Map<String, Object> configs = new HashMap<>();
-      template.getTemplateConfigs().forEach((key, value) -> configs.put(key, value.getValue()));
-      PipelineElementTemplateVisitor visitor = new PipelineElementTemplateVisitor(configs);
-      pipelineElement.getStaticProperties().forEach(config -> config.accept(visitor));
-
-      if (overwriteNameAndDescription) {
-        pipelineElement.setName(template.getTemplateName());
-        pipelineElement.setDescription(template.getTemplateDescription());
-      }
-
-      return pipelineElement;
+  protected void visitStaticProperties(PipelineElementTemplateVisitor visitor) {
+    element.getStaticProperties().forEach(config -> config.accept(visitor));
   }
+
+  protected void applyNameAndDescription(String name, String description) {
+    element.setName(name);
+    element.setDescription(description);
+  }
+
+
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
index 5da9a2b..4c533aa 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
@@ -127,8 +127,10 @@
       Map<String, Object> values = getAsMap(staticPropertyAlternative);
       StaticProperty property = staticPropertyAlternative.getStaticProperty();
       staticPropertyAlternative.setSelected(Boolean.parseBoolean(String.valueOf(values.get("selected"))));
-      PipelineElementTemplateVisitor visitor = new PipelineElementTemplateVisitor(getAsMap(values, "staticProperty"));
-      property.accept(visitor);
+      if (property != null) {
+        PipelineElementTemplateVisitor visitor = new PipelineElementTemplateVisitor(getAsMap(values, "staticProperty"));
+        property.accept(visitor);
+      }
     }
   }
 
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineGenerator.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineGenerator.java
index 63957d8..33e61cc 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineGenerator.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineGenerator.java
@@ -63,7 +63,7 @@
     pipeline.setStreams(Collections.singletonList(prepareStream(datasetId)));
     pipeline.setSepas(new ArrayList<>());
     pipeline.setActions(new ArrayList<>());
-    collectInvocations("domId" + count, pipelineTemplateDescription.getBoundTo());
+    collectInvocations("jsplumb_domId" + count, pipelineTemplateDescription.getBoundTo());
 
     return pipeline;
   }
@@ -145,6 +145,6 @@
 
   private String getDom() {
     count++;
-    return "domId" + count;
+    return "jsplumb_domId" + count;
   }
 }
diff --git a/streampipes-platform-services/pom.xml b/streampipes-platform-services/pom.xml
index 5558c74..2f7d6aa 100644
--- a/streampipes-platform-services/pom.xml
+++ b/streampipes-platform-services/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -31,27 +31,27 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-data-explorer</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-rest-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-api</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-rest</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <dependency>
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResourceV3.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV3.java
similarity index 96%
rename from streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResourceV3.java
rename to streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV3.java
index 57e3b93..877b884 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResourceV3.java
+++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV3.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.streampipes.rest.impl.datalake;
+package org.apache.streampipes.ps;
 
 import org.apache.streampipes.dataexplorer.DataLakeNoUserManagementV3;
 import org.apache.streampipes.model.schema.EventSchema;
@@ -28,6 +28,7 @@
 import javax.ws.rs.core.Response;
 
 @Path("/v3/datalake/measure")
+@Deprecated
 public class DataLakeMeasureResourceV3 extends AbstractAuthGuardedRestResource {
 
     private DataLakeNoUserManagementV3 dataLakeManagement;
diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV4.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV4.java
new file mode 100644
index 0000000..9f71f16
--- /dev/null
+++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV4.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.ps;
+
+import org.apache.streampipes.dataexplorer.DataLakeManagementV4;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
+import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/v4/datalake/measure")
+public class DataLakeMeasureResourceV4 extends AbstractAuthGuardedRestResource {
+
+    private DataLakeManagementV4 dataLakeManagement;
+
+    public DataLakeMeasureResourceV4() {
+        this.dataLakeManagement = new DataLakeManagementV4();
+    }
+
+    @POST
+    @JacksonSerialized
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("/")
+    public Response addDataLake(DataLakeMeasure dataLakeMeasure) {
+        DataLakeMeasure result = this.dataLakeManagement.addDataLake(dataLakeMeasure);
+        return ok(result);
+    }
+
+    @GET
+    @JacksonSerialized
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("{id}")
+    public Response getDataLakeMeasure(@PathParam("id") String measureId) {
+        return ok(this.dataLakeManagement.getById(measureId));
+    }
+}
diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV3.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV3.java
index 900a812..00fd8c9 100644
--- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV3.java
+++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV3.java
@@ -31,41 +31,11 @@
 import java.util.List;
 
 @Path("/v3/datalake")
+@Deprecated
 public class DataLakeResourceV3 extends AbstractRestResource {
-//  private DataLakeManagementV3 dataLakeManagement;
-//
   public DataLakeResourceV3() {
   }
-//
-//  public DataLakeResourceV3(DataLakeManagementV3 dataLakeManagement) {
-//    this.dataLakeManagement = dataLakeManagement;
-//  }
-//
-////  @GET
-////  @Produces(MediaType.APPLICATION_JSON)
-////  @GsonWithIds
-////  @Path("/data/{index}/paging")
-////  public Response getPage(@PathParam("index") String index,
-////                          @Context UriInfo info,
-////                          @QueryParam("itemsPerPage") int itemsPerPage) {
-////
-////    PageResult result;
-////    String page = info.getQueryParameters().getFirst("page");
-////
-////    try {
-////      if (page != null) {
-////        result = this.dataLakeManagement.getEvents(index, itemsPerPage, Integer.parseInt(page));
-////      } else {
-////        result = this.dataLakeManagement.getEvents(index, itemsPerPage);
-////      }
-////      return Response.ok(result).build();
-////    } catch (IOException e) {
-////      e.printStackTrace();
-////
-////      return Response.serverError().build();
-////    }
-////  }
-//
+
   @GET
   @JacksonSerialized
   @Produces(MediaType.APPLICATION_JSON)
@@ -74,168 +44,5 @@
     List<DataLakeMeasure> result = DataExplorerUtils.getInfos();
     return ok(result);
   }
-//
-//  @Deprecated
-//  @GET
-//  @Produces(MediaType.APPLICATION_OCTET_STREAM)
-//  @Path("/data/{index}")
-//  public Response getAllData(@PathParam("index") String index,
-//                             @QueryParam("format") String format) {
-//    StreamingOutput streamingOutput = output -> dataLakeManagement.getAllEvents(index, format, output);
-//
-//    return Response.ok(streamingOutput, MediaType.APPLICATION_OCTET_STREAM).
-//            header("Content-Disposition", "attachment; filename=\"datalake." + format + "\"")
-//            .build();
-//  }
-//
-//  @GET
-//  @Produces(MediaType.APPLICATION_OCTET_STREAM)
-//  @Path("/data/{index}/download")
-//  public Response downloadData(@PathParam("index") String index,
-//                               @QueryParam("format") String format) {
-//    StreamingOutput streamingOutput = output -> dataLakeManagement.getAllEvents(index, format, output);
-//
-//    return Response.ok(streamingOutput, MediaType.APPLICATION_OCTET_STREAM).
-//            header("Content-Disposition", "attachment; filename=\"datalake." + format + "\"")
-//            .build();
-//  }
-//
-//  @GET
-//  @Produces(MediaType.APPLICATION_JSON)
-//  @Path("/data/{index}/last/{value}/{unit}")
-//  public Response getAllData(@PathParam("index") String index,
-//                             @PathParam("value") int value,
-//                             @PathParam("unit") String unit,
-//                             @Context UriInfo info) {
-//
-//
-//    String aggregationUnit = info.getQueryParameters().getFirst("aggregationUnit");
-//    String aggregationValue = info.getQueryParameters().getFirst("aggregationValue");
-//
-//    DataSeries result;
-//    try {
-//      if (aggregationUnit != null && aggregationValue != null) {
-//        result = dataLakeManagement.getEventsFromNow(index, unit, value, aggregationUnit,
-//                Integer.parseInt(aggregationValue));
-//      } else {
-//        result = dataLakeManagement.getEventsFromNowAutoAggregation(index, unit, value);
-//      }
-//      return Response.ok(result).build();
-//    } catch (RuntimeException e) {
-//      return constructErrorMessage(new Notification(e.getMessage(), ""));
-//    }
-//  }
-//
-//  @GET
-//  @Produces(MediaType.APPLICATION_JSON)
-//  @Path("/data/{index}/{startdate}/{enddate}")
-//  public Response getAllData(@Context UriInfo info,
-//                             @PathParam("index") String index,
-//                             @PathParam("startdate") long startdate,
-//                             @PathParam("enddate") long enddate) {
-//
-//    String aggregationUnit = info.getQueryParameters().getFirst("aggregationUnit");
-//    String aggregationValue = info.getQueryParameters().getFirst("aggregationValue");
-//
-//    DataSeries result;
-//
-//    try {
-//      if (aggregationUnit != null && aggregationValue != null) {
-//        result = dataLakeManagement.getEvents(index, startdate, enddate, aggregationUnit,
-//                Integer.parseInt(aggregationValue));
-//
-//      } else {
-//        result = dataLakeManagement.getEventsAutoAggregation(index, startdate, enddate);
-//      }
-//      return Response.ok(result).build();
-//    } catch (RuntimeException e) {
-//      return constructErrorMessage(new Notification(e.getMessage(), ""));
-//    }
-//  }
-//
-//  @GET
-//  @Produces(MediaType.APPLICATION_JSON)
-//  @Path("/data/{index}/{startdate}/{enddate}/grouping/{groupingTag}")
-//  public Response getAllDataGrouping(@Context UriInfo info,
-//                                     @PathParam("index") String index,
-//                                     @PathParam("startdate") long startdate,
-//                                     @PathParam("enddate") long enddate,
-//                                     @PathParam("groupingTag") String groupingTag) {
-//
-//    String aggregationUnit = info.getQueryParameters().getFirst("aggregationUnit");
-//    String aggregationValue = info.getQueryParameters().getFirst("aggregationValue");
-//
-//    SPQueryResult result;
-//    try {
-//      if (aggregationUnit != null && aggregationValue != null) {
-//        result = dataLakeManagement.getEvents(index, startdate, enddate, aggregationUnit,
-//                Integer.parseInt(aggregationValue), groupingTag);
-//      } else {
-//        result = dataLakeManagement.getEventsAutoAggregation(index, startdate, enddate, groupingTag);
-//      }
-//      return Response.ok(result).build();
-//    } catch (RuntimeException e) {
-//      return constructErrorMessage(new Notification(e.getMessage(), ""));
-//    }
-//  }
-//
-//  @DELETE
-//  @Produces(MediaType.APPLICATION_JSON)
-//  @Path("/data/delete/all")
-//  public Response removeAllData() {
-//
-//    boolean result = dataLakeManagement.removeAllDataFromDataLake();
-//
-//    return Response.ok(result).build();
-//  }
-//
-//  @GET
-//  @Produces(MediaType.APPLICATION_OCTET_STREAM)
-//  @Path("/data/{index}/{startdate}/{enddate}/download")
-//  public Response downloadData(@PathParam("index") String index, @QueryParam("format") String format,
-//                               @PathParam("startdate") long start, @PathParam("enddate") long end) {
-//    StreamingOutput streamingOutput = output -> dataLakeManagement.getAllEvents(index, format, start, end, output);
-//
-//    return Response.ok(streamingOutput, MediaType.APPLICATION_OCTET_STREAM).
-//            header("Content-Disposition", "attachment; filename=\"datalake." + format + "\"")
-//            .build();
-//  }
-//
-//  @GET
-//  @Path("/data/image/{route}/file")
-//  @Produces("image/png")
-//  public Response getImage(@PathParam("route") String fileRoute) throws IOException {
-//    return ok(dataLakeManagement.getImage(fileRoute));
-//  }
-//
-//  @POST
-//  @Path("/data/image/{route}/coco")
-//  public void saveImageCoco(@PathParam("route") String fileRoute, String data) throws IOException {
-//    dataLakeManagement.saveImageCoco(fileRoute, data);
-//  }
-//
-//  @GET
-//  @Path("/data/image/{route}/coco")
-//  @Produces("application/json")
-//  public Response getImageCoco(@PathParam("route") String fileRoute) throws IOException {
-//    return ok(dataLakeManagement.getImageCoco(fileRoute));
-//  }
-//
-//  @POST
-//  @Produces(MediaType.TEXT_PLAIN)
-//  @Path("/data/{index}/{startdate}/{enddate}/labeling/{column}/{timestampColumn}")
-//  public Response labelData(@Context UriInfo info,
-//                            @PathParam("index") String index,
-//                            @PathParam("startdate") long startdate,
-//                            @PathParam("enddate") long enddate,
-//                            @PathParam("column") String column,
-//                            @PathParam("timestampColumn") String timestampColumn) {
-//
-//    String label = info.getQueryParameters().getFirst("label");
-//    this.dataLakeManagement.updateLabels(index, column, startdate, enddate, label, timestampColumn);
-//
-//    return Response.ok("Successfully updated database.", MediaType.TEXT_PLAIN).build();
-//  }
-//
-//
+
 }
diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java
index 4791b4c..840e939 100644
--- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java
+++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java
@@ -27,6 +27,7 @@
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import org.apache.streampipes.dataexplorer.DataLakeManagementV4;
 import org.apache.streampipes.dataexplorer.v4.ProvidedQueryParams;
+import org.apache.streampipes.model.StreamPipesErrorMessage;
 import org.apache.streampipes.model.datalake.DataLakeConfiguration;
 import org.apache.streampipes.model.datalake.DataLakeMeasure;
 import org.apache.streampipes.rest.core.base.impl.AbstractRestResource;
@@ -40,13 +41,10 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import static org.apache.streampipes.dataexplorer.v4.SupportedDataLakeQueryParameters.*;
 
-class Placeholder {
-}
-
-
 @Path("v4/datalake")
 public class DataLakeResourceV4 extends AbstractRestResource {
 
@@ -156,19 +154,33 @@
 
         MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
 
-        if (! (checkProvidedQueryParams(queryParams))) {
+        if (!(checkProvidedQueryParams(queryParams))) {
             return badRequest();
         } else {
             ProvidedQueryParams sanitizedParams = populate(measurementID, queryParams);
             try {
                 SpQueryResult result = this.dataLakeManagement.getData(sanitizedParams);
                 return ok(result);
-            } catch (IllegalArgumentException e) {
-                return badRequest(e.getMessage());
+            } catch (RuntimeException e) {
+                return badRequest(StreamPipesErrorMessage.from(e));
             }
         }
     }
 
+    @POST
+    @Path("/query")
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response getData(List<Map<String, String>> queryParams) {
+        var results = queryParams
+          .stream()
+          .map(qp -> new ProvidedQueryParams(qp.get("measureName"), qp))
+          .map(params -> this.dataLakeManagement.getData(params))
+          .collect(Collectors.toList());
+
+        return ok(results);
+    }
+
     @GET
     @Path("/measurements/{measurementID}/download")
     @Produces(MediaType.APPLICATION_OCTET_STREAM)
@@ -188,6 +200,7 @@
             , @Parameter(in = ParameterIn.QUERY, description = "name of aggregation function used for grouping operation") @QueryParam(QP_AGGREGATION_FUNCTION) String aggregationFunction
             , @Parameter(in = ParameterIn.QUERY, description = "time interval for aggregation (e.g. 1m - one minute) for grouping operation") @QueryParam(QP_TIME_INTERVAL) String timeInterval
             , @Parameter(in = ParameterIn.QUERY, description = "format specification (csv, json - default is csv) for data download") @QueryParam(QP_FORMAT) String format
+            , @Parameter(in = ParameterIn.QUERY, description = "csv delimiter (comma or semicolon)") @QueryParam(QP_CSV_DELIMITER) String csvDelimiter
             , @Parameter(in = ParameterIn.QUERY, description = "filter conditions (a comma-separated list of filter conditions such as [field,operator,condition])") @QueryParam(QP_FILTER) String filter
             , @Context UriInfo uriInfo) {
 
@@ -219,23 +232,6 @@
         return ok(this.dataLakeManagement.getDataLakeConfiguration());
     }
 
-    @POST
-    @Path("/measurements/{measurementID}/labeling")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Operation(summary = "Label data points of the measurement series with given id", tags = {"Data Lake"},
-            responses = {
-                    @ApiResponse(responseCode = "200", description = "Labeling was successful")})
-    public Response labelData(@Parameter(in = ParameterIn.PATH, description = "the id of the measurement series", required = true) @PathParam("measurementID") String measurementID
-            , @Parameter(in = ParameterIn.DEFAULT, description = "the label details that should be written into database") Placeholder body
-
-            , @Parameter(in = ParameterIn.QUERY, description = "start date for slicing operation") @QueryParam("startDate") String startDate
-            , @Parameter(in = ParameterIn.QUERY, description = "end date for slicing operation") @QueryParam("endDate") String endDate) {
-        /**
-         * TODO: implementation of method stump
-         */
-        return null;
-    }
-
     @DELETE
     @Path("/measurements")
     @Operation(summary = "Remove all stored measurement series from Data Lake", tags = {"Data Lake"},
diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/PipelineElementTemplateResource.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/PipelineElementTemplateResource.java
index dfa5bbc..d159e2e 100644
--- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/PipelineElementTemplateResource.java
+++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/PipelineElementTemplateResource.java
@@ -24,8 +24,10 @@
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.parameters.RequestBody;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import org.apache.streampipes.manager.template.AdapterTemplateHandler;
 import org.apache.streampipes.manager.template.DataProcessorTemplateHandler;
 import org.apache.streampipes.manager.template.DataSinkTemplateHandler;
+import org.apache.streampipes.model.connect.adapter.AdapterDescription;
 import org.apache.streampipes.model.graph.DataProcessorInvocation;
 import org.apache.streampipes.model.graph.DataSinkInvocation;
 import org.apache.streampipes.model.template.PipelineElementTemplate;
@@ -194,4 +196,32 @@
     return ok(new DataProcessorTemplateHandler(template, invocation, Boolean.parseBoolean(overwriteNameAndDescription))
             .applyTemplateOnPipelineElement());
   }
+
+  @POST
+  @Path("{id}/adapter")
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  @JacksonSerialized
+  @Operation(summary = "Configure an adapter with a pipeline element template.",
+    tags = {"Pipeline Element Templates"},
+    responses = {
+      @ApiResponse(content = {
+        @Content(
+          mediaType = "application/json",
+          schema = @Schema(implementation = AdapterDescription.class))
+      }, responseCode = "200", description = "The configured adapter model"),
+    })
+  public Response getPipelineElementForTemplate(@Parameter(description = "The id of the pipeline element template", required = true)
+                                                @PathParam("id") String id,
+
+                                                @Parameter(description = "Overwrite the name and description of the pipeline element with the labels given in the pipeline element template")
+                                                @QueryParam("overwriteNames") String overwriteNameAndDescription,
+
+                                                @RequestBody(description = "The adapter that should be configured with the template contents",
+                                                  content = @Content(schema = @Schema(implementation = AdapterDescription.class))) AdapterDescription adapterDescription) {
+    PipelineElementTemplate template = getPipelineElementTemplateStorage().getElementById(id);
+    var desc = new AdapterTemplateHandler(template, adapterDescription, Boolean.parseBoolean(overwriteNameAndDescription))
+      .applyTemplateOnPipelineElement();
+    return ok(desc);
+  }
 }
diff --git a/streampipes-resource-management/pom.xml b/streampipes-resource-management/pom.xml
index 9a63661..68f3dbf 100644
--- a/streampipes-resource-management/pom.xml
+++ b/streampipes-resource-management/pom.xml
@@ -16,13 +16,11 @@
   ~ limitations under the License.
   ~
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,17 +30,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-mail</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-user-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AbstractPipelineElementResourceManager.java b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AbstractPipelineElementResourceManager.java
index 90b31c3..ad77da9 100644
--- a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AbstractPipelineElementResourceManager.java
+++ b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AbstractPipelineElementResourceManager.java
@@ -56,8 +56,10 @@
 
   public void delete(String elementId) {
     D description = find(elementId);
-    deleteAssetsAndPermissions(description);
-    db.deleteElement(description);
+    if (description != null) {
+      deleteAssetsAndPermissions(description);
+      db.deleteElement(description);
+    }
   }
 
   private void deleteAssetsAndPermissions(D description) {
diff --git a/streampipes-rest-core-base/pom.xml b/streampipes-rest-core-base/pom.xml
index d835f7c..7768c0f 100644
--- a/streampipes-rest-core-base/pom.xml
+++ b/streampipes-rest-core-base/pom.xml
@@ -17,13 +17,11 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -33,22 +31,22 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-rest-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-user-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/streampipes-rest-shared/pom.xml b/streampipes-rest-shared/pom.xml
index 606d5ad..836a9de 100644
--- a/streampipes-rest-shared/pom.xml
+++ b/streampipes-rest-shared/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>streampipes-parent</artifactId>
 		<groupId>org.apache.streampipes</groupId>
-		<version>0.70.0-SNAPSHOT</version>
+		<version>0.71.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 
@@ -32,7 +32,7 @@
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-commons</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 			<exclusions>
 				<exclusion>
 					<groupId>org.apache.httpcomponents</groupId>
@@ -43,7 +43,7 @@
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-serializers-json</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 
 		<!-- External dependencies -->
diff --git a/streampipes-rest/pom.xml b/streampipes-rest/pom.xml
index 8cedd5b..4daa862 100644
--- a/streampipes-rest/pom.xml
+++ b/streampipes-rest/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <name>StreamPipes REST API</name>
     <artifactId>streampipes-rest</artifactId>
@@ -32,7 +32,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-commons</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.apache.httpcomponents</groupId>
@@ -43,67 +43,72 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-data-explorer</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-data-export</artifactId>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-measurement-units</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-jms</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-mail</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-pipeline-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-rest-shared</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-serializers-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-discovery</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-user-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-rest-core-base</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-connect-container-master</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java
new file mode 100644
index 0000000..663e96a
--- /dev/null
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.rest.impl;
+
+import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
+import org.apache.streampipes.rest.security.AuthConstants;
+import org.apache.streampipes.storage.api.IGenericStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+@Path("/v2/storage-generic")
+@Component
+@PreAuthorize(AuthConstants.IS_ADMIN_ROLE)
+public class GenericStorageResource extends AbstractAuthGuardedRestResource {
+
+    public static final String APP_DOC_NAME = "appDocName";
+
+    private static final Logger LOG = LoggerFactory.getLogger(GenericStorageResource.class);
+
+    @GET
+    @Path("{appDocName}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getAll(@PathParam(APP_DOC_NAME) String appDocName) {
+      try {
+        List<Map<String, Object>> assets = getGenericStorage().findAll(appDocName);
+        return ok(assets);
+      } catch (IOException e) {
+        LOG.error("Could not connect to storage", e);
+        return fail();
+      }
+    }
+
+    @POST
+    @Path("{appDocName}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response create(@PathParam(APP_DOC_NAME) String appDocName,
+                           String document) {
+      try {
+        Map<String, Object> obj = getGenericStorage().create(document);
+        return ok(obj);
+      } catch (IOException e) {
+        LOG.error("Could not connect to storage", e);
+        return fail();
+      }
+    }
+
+    @GET
+    @Path("{appDocName}/{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getCategory(@PathParam(APP_DOC_NAME) String appDocName,
+                                @PathParam("id") String documentId) {
+      try {
+        Map<String, Object> obj = getGenericStorage().findOne(documentId);
+        return ok(obj);
+      } catch (IOException e) {
+        LOG.error("Could not connect to storage", e);
+        return fail();
+      }
+    }
+
+    @PUT
+    @Path("{appDocName}/{id}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response update(@PathParam(APP_DOC_NAME) String appDocName,
+                           @PathParam("id") String documentId,
+                           String document) {
+      try {
+        Map<String, Object> obj = getGenericStorage().update(documentId, document);
+        return ok(obj);
+      } catch (IOException e) {
+        LOG.error("Could not connect to storage", e);
+        return fail();
+      }
+    }
+
+    @DELETE
+    @Path("{appDocName}/{id}/{rev}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response delete(@PathParam(APP_DOC_NAME) String appDocName,
+                           @PathParam("id") String documentId,
+                           @PathParam("rev") String rev) {
+      try {
+        getGenericStorage().delete(documentId, rev);
+        return ok();
+      } catch (IOException e) {
+        LOG.error("Could not connect to storage", e);
+        return fail();
+      }
+    }
+
+    private IGenericStorage getGenericStorage() {
+      return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage();
+    }
+
+  }
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/AssetManagementResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/AssetManagementResource.java
new file mode 100644
index 0000000..d0317ae
--- /dev/null
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/AssetManagementResource.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.rest.impl.admin;
+
+import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
+import org.apache.streampipes.rest.security.AuthConstants;
+import org.apache.streampipes.storage.api.IGenericStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+
+@Path("/v2/assets")
+@Component
+@PreAuthorize(AuthConstants.IS_ADMIN_ROLE)
+public class AssetManagementResource extends AbstractAuthGuardedRestResource {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AssetManagementResource.class);
+
+  private static final String APP_DOC_TYPE = "asset-management";
+
+  @GET
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response getAll() {
+    try {
+      List<Map<String, Object>> assets = getGenericStorage().findAll(APP_DOC_TYPE);
+      return ok(assets);
+    } catch (IOException e) {
+      LOG.error("Could not connect to storage", e);
+      return fail();
+    }
+  }
+
+  @POST
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response create(String asset) {
+    try {
+      Map<String, Object> obj = getGenericStorage().create(asset);
+      return ok(obj);
+    } catch (IOException e) {
+      LOG.error("Could not connect to storage", e);
+      return fail();
+    }
+  }
+
+  @GET
+  @Path("/{id}")
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response getCategory(@PathParam("id") String assetId) {
+    try {
+      Map<String, Object> obj = getGenericStorage().findOne(assetId);
+      return ok(obj);
+    } catch (IOException e) {
+      LOG.error("Could not connect to storage", e);
+      return fail();
+    }
+  }
+
+  @PUT
+  @Path("/{id}")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response update(@PathParam("id") String assetId, String asset) {
+    try {
+      Map<String, Object> obj = getGenericStorage().update(assetId, asset);
+      return ok(obj);
+    } catch (IOException e) {
+      LOG.error("Could not connect to storage", e);
+      return fail();
+    }
+  }
+
+  @DELETE
+  @Path("/{id}/{rev}")
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response delete(@PathParam("id") String assetId, @PathParam("rev") String rev) {
+    try {
+      getGenericStorage().delete(assetId, rev);
+      return ok();
+    } catch (IOException e) {
+      LOG.error("Could not connect to storage", e);
+      return fail();
+    }
+  }
+
+  private IGenericStorage getGenericStorage() {
+    return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage();
+  }
+
+
+}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/DataExportResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/DataExportResource.java
new file mode 100644
index 0000000..fff7945
--- /dev/null
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/DataExportResource.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.rest.impl.admin;
+
+import org.apache.streampipes.export.ExportManager;
+import org.apache.streampipes.model.export.ExportConfiguration;
+import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
+import org.apache.streampipes.rest.security.AuthConstants;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.List;
+
+@Path("/v2/export")
+@Component
+@PreAuthorize(AuthConstants.IS_ADMIN_ROLE)
+public class DataExportResource extends AbstractAuthGuardedRestResource {
+
+  @Path("/preview")
+  @POST
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response getExportPreview(List<String> selectedAssetIds) {
+    var exportConfig = ExportManager.getExportPreview(selectedAssetIds);
+    return ok(exportConfig);
+  }
+
+  @Path("/download")
+  @POST
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_OCTET_STREAM)
+  public Response getExportPreview(ExportConfiguration exportConfiguration) throws IOException {
+      var applicationPackage = ExportManager.getExportPackage(exportConfiguration);
+      return ok(applicationPackage);
+  }
+
+}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/DataImportResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/DataImportResource.java
new file mode 100644
index 0000000..61b8b4f
--- /dev/null
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/DataImportResource.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.rest.impl.admin;
+
+import org.apache.streampipes.export.ImportManager;
+import org.apache.streampipes.model.export.AssetExportConfiguration;
+import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
+import org.apache.streampipes.rest.security.AuthConstants;
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+
+@Path("/v2/import")
+@Component
+@PreAuthorize(AuthConstants.IS_ADMIN_ROLE)
+public class DataImportResource extends AbstractAuthGuardedRestResource {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DataImportResource.class);
+
+  @Path("/preview")
+  @POST
+  @Consumes(MediaType.MULTIPART_FORM_DATA)
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response getImportPreview(@FormDataParam("file_upload") InputStream uploadedInputStream,
+                                   @FormDataParam("file_upload") FormDataContentDisposition fileDetail) throws IOException {
+    var importConfig =  ImportManager.getImportPreview(uploadedInputStream);
+    return ok(importConfig);
+  }
+
+  @POST
+  @Consumes(MediaType.MULTIPART_FORM_DATA)
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response importData(@FormDataParam("file_upload") InputStream uploadedInputStream,
+                             @FormDataParam("file_upload") FormDataContentDisposition fileDetail,
+                             @FormDataParam("configuration") AssetExportConfiguration exportConfiguration) {
+    try {
+      ImportManager.performImport(uploadedInputStream, exportConfiguration, getAuthenticatedUserSid());
+      return ok();
+    } catch (IOException e) {
+      LOG.error("An error occurred while importing resources", e);
+      return fail();
+    }
+
+  }
+}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
index 9935ee1..477fe9f 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
@@ -20,6 +20,7 @@
 
 import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.container.master.management.AdapterMasterManagement;
+import org.apache.streampipes.model.StreamPipesErrorMessage;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
 import org.apache.streampipes.model.message.Notifications;
 import org.apache.streampipes.rest.security.AuthConstants;
@@ -92,7 +93,7 @@
             return ok(Notifications.success("Adapter started"));
         } catch (AdapterException e) {
             LOG.error("Could not stop adapter with id " +adapterId, e);
-            return ok(Notifications.error(e.getMessage()));
+            return serverError(StreamPipesErrorMessage.from(e));
         }
     }
 
@@ -107,7 +108,7 @@
             return ok(Notifications.success("Adapter stopped"));
         } catch (AdapterException e) {
             LOG.error("Could not start adapter with id " +adapterId, e);
-            return ok(Notifications.error(e.getMessage()));
+            return serverError(StreamPipesErrorMessage.from(e));
         }
     }
 
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/DescriptionResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/DescriptionResource.java
index 90e6508..5681952 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/DescriptionResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/DescriptionResource.java
@@ -18,6 +18,7 @@
 package org.apache.streampipes.rest.impl.connect;
 
 import org.apache.streampipes.commons.exceptions.NoServiceEndpointsAvailableException;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.container.master.management.DescriptionManagement;
 import org.apache.streampipes.connect.container.master.management.WorkerUrlProvider;
@@ -27,10 +28,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import javax.ws.rs.*;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.util.List;
@@ -154,4 +152,15 @@
             return fail();
         }
     }
+
+    @DELETE
+    @Path("{adapterId}")
+    public Response deleteAdapter(@PathParam("adapterId") String adapterId) {
+        try {
+            this.managementService.deleteAdapterDescription(adapterId);
+            return ok();
+        } catch (SpRuntimeException e) {
+            return badRequest(e);
+        }
+    }
 }
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/GuessResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/GuessResource.java
index 474c119..b678b9e 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/GuessResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/GuessResource.java
@@ -18,21 +18,25 @@
 
 package org.apache.streampipes.rest.impl.connect;
 
+import org.apache.streampipes.commons.exceptions.NoServiceEndpointsAvailableException;
 import org.apache.streampipes.connect.api.exception.ParseException;
 import org.apache.streampipes.connect.api.exception.WorkerAdapterException;
 import org.apache.streampipes.connect.container.master.management.GuessManagement;
+import org.apache.streampipes.model.StreamPipesErrorMessage;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import org.apache.streampipes.model.connect.guess.AdapterEventPreview;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
-import org.apache.streampipes.model.message.Notifications;
 import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.ws.rs.Consumes;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import java.io.IOException;
 
 
 @Path("/v2/connect/master/guess")
@@ -56,13 +60,22 @@
           return ok(result);
       } catch (ParseException e) {
           LOG.error("Error while parsing events: ", e);
-          return serverError(Notifications.error(e.getMessage()));
+          return badRequest(StreamPipesErrorMessage.from(e));
       } catch (WorkerAdapterException e) {
-          return serverError(e.getContent());
-      } catch (Exception e) {
-          LOG.error("Error while guess schema for AdapterDescription: ", e);
-          return serverError(Notifications.error(e.getMessage()));
+          return serverError(StreamPipesErrorMessage.from(e));
+      } catch (NoServiceEndpointsAvailableException | IOException e) {
+        LOG.error(e.getMessage());
+        return serverError(StreamPipesErrorMessage.from(e));
       }
   }
+
+  @POST
+  @JacksonSerialized
+  @Path("/schema/preview")
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  public Response getAdapterEventPreview(AdapterEventPreview previewRequest) {
+    return ok(managementService.performAdapterEventPreview(previewRequest));
+  }
 }
 
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/RuntimeResolvableResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/RuntimeResolvableResource.java
index 1db6196..5f3fe1f 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/RuntimeResolvableResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/RuntimeResolvableResource.java
@@ -19,13 +19,17 @@
 package org.apache.streampipes.rest.impl.connect;
 
 import org.apache.streampipes.commons.exceptions.NoServiceEndpointsAvailableException;
+import org.apache.streampipes.commons.exceptions.SpConfigurationException;
 import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.container.master.management.WorkerAdministrationManagement;
 import org.apache.streampipes.connect.container.master.management.WorkerRestClient;
 import org.apache.streampipes.connect.container.master.management.WorkerUrlProvider;
+import org.apache.streampipes.model.StreamPipesErrorMessage;
 import org.apache.streampipes.model.runtime.RuntimeOptionsRequest;
 import org.apache.streampipes.model.runtime.RuntimeOptionsResponse;
 import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.ws.rs.*;
 import javax.ws.rs.core.MediaType;
@@ -34,6 +38,8 @@
 @Path("/v2/connect/master/resolvable")
 public class RuntimeResolvableResource extends AbstractAdapterResource<WorkerAdministrationManagement> {
 
+    private static final Logger LOG = LoggerFactory.getLogger(RuntimeResolvableResource.class);
+
     private final WorkerUrlProvider workerUrlProvider;
 
     public RuntimeResolvableResource() {
@@ -56,11 +62,16 @@
             RuntimeOptionsResponse result = WorkerRestClient.getConfiguration(workerEndpoint, appId, runtimeOptionsRequest);
 
             return ok(result);
-        } catch (AdapterException | NoServiceEndpointsAvailableException e) {
-            e.printStackTrace();
-            return fail();
+        } catch (AdapterException e) {
+            LOG.error("Adapter exception occurred", e);
+            return serverError(StreamPipesErrorMessage.from(e));
+        } catch (NoServiceEndpointsAvailableException e) {
+            LOG.error("Could not find service endpoint for {} while fetching configuration", appId);
+            return serverError(StreamPipesErrorMessage.from(e));
+        } catch (SpConfigurationException e) {
+            LOG.error("Tried to fetch a runtime configuration with insufficient settings");
+            return badRequest(StreamPipesErrorMessage.from(e));
         }
-
     }
 
 }
diff --git a/streampipes-sdk-bundle/pom.xml b/streampipes-sdk-bundle/pom.xml
index 929ad16..8b3629c 100644
--- a/streampipes-sdk-bundle/pom.xml
+++ b/streampipes-sdk-bundle/pom.xml
@@ -16,13 +16,11 @@
   ~ limitations under the License.
   ~
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,47 +30,47 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container-extensions</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-cbor</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-smile</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-dataformat-fst</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-jms</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-kafka</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-mqtt</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/streampipes-sdk/pom.xml b/streampipes-sdk/pom.xml
index e99e80e..d801c0e 100644
--- a/streampipes-sdk/pom.xml
+++ b/streampipes-sdk/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
        <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,17 +32,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-vocabulary</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
index efacba4..2d3cabd 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
@@ -48,6 +48,12 @@
     return freeTextProperty(label, Datatypes.String);
   }
 
+  public static FreeTextStaticProperty stringFreeTextProperty(Label label, String defaultValue) {
+    var property = freeTextProperty(label, Datatypes.String);
+    property.setValue(defaultValue);
+    return property;
+  }
+
   public static FreeTextStaticProperty integerFreeTextProperty(Label label) {
     return freeTextProperty(label, Datatypes.Integer);
   }
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
index b3b4cfb..5665fce 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
@@ -260,7 +260,7 @@
   }
 
   /**
-   * @deprecated Use {@link #requiredTextParameter(Label, String)}
+   * @deprecated Use {@link #requiredTextParameterWithLink(Label, String)}
    * @param internalId
    * @param label
    * @param description
@@ -284,10 +284,27 @@
    * value range of the parameter is restricted to the value specification of a selected input event property.
    * @param label The {@link org.apache.streampipes.sdk.helpers.Label} that describes why this parameter is needed in a
    *              user-friendly manner.
+   * @param defaultValue The default value is displayed to the user in the input field
+   * @return this
+   */
+  public BU requiredTextParameter(Label label,
+                                  String defaultValue) {
+    FreeTextStaticProperty fsp = StaticProperties.stringFreeTextProperty(label, defaultValue);
+
+    this.staticProperties.add(fsp);
+    return me();
+  }
+
+
+  /**
+   * Defines a text-based configuration parameter provided by pipeline developers at pipeline authoring time. The
+   * value range of the parameter is restricted to the value specification of a selected input event property.
+   * @param label The {@link org.apache.streampipes.sdk.helpers.Label} that describes why this parameter is needed in a
+   *              user-friendly manner.
    * @param linkedMappingPropertyInternalName The inernalId of the {@link org.apache.streampipes.model.staticproperty.MappingProperty}
    * @return this
    */
-  public BU requiredTextParameter(Label label, String
+  public BU requiredTextParameterWithLink(Label label, String
           linkedMappingPropertyInternalName) {
     FreeTextStaticProperty fsp = prepareFreeTextStaticProperty(label, XSD._string.toString());
 
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/adapter/GuessSchemaBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/adapter/GuessSchemaBuilder.java
index 91e0da1..8f88a54 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/adapter/GuessSchemaBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/adapter/GuessSchemaBuilder.java
@@ -18,18 +18,20 @@
 package org.apache.streampipes.sdk.builder.adapter;
 
 import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.connect.guess.GuessTypeInfo;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventSchema;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 public class GuessSchemaBuilder {
 
   private List<EventProperty> eventProperties;
+  private Map<String, GuessTypeInfo> samples;
 
   private GuessSchemaBuilder() {
     this.eventProperties = new ArrayList<>();
+    this.samples = new HashMap<>();
   }
 
   /**
@@ -39,6 +41,13 @@
     return new GuessSchemaBuilder();
   }
 
+  public GuessSchemaBuilder sample(String runtimeName,
+                                   Object sampleValue) {
+    this.samples.put(runtimeName, new GuessTypeInfo(sampleValue.getClass().getCanonicalName(), sampleValue));
+
+    return this;
+  }
+
   public GuessSchemaBuilder property(EventProperty property) {
     this.eventProperties.add(property);
 
@@ -56,6 +65,7 @@
     eventSchema.setEventProperties(eventProperties);
 
     guessSchema.setEventSchema(eventSchema);
+    guessSchema.setEventPreview(List.of(this.samples));
 
     return guessSchema;
   }
diff --git a/streampipes-security-jwt/pom.xml b/streampipes-security-jwt/pom.xml
index 13b7a8e..2128339 100644
--- a/streampipes-security-jwt/pom.xml
+++ b/streampipes-security-jwt/pom.xml
@@ -16,13 +16,11 @@
   ~ limitations under the License.
   ~
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,7 +30,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-commons</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>io.jsonwebtoken</groupId>
diff --git a/streampipes-serializers-json/pom.xml b/streampipes-serializers-json/pom.xml
index 1fd8b26..fb88b77 100644
--- a/streampipes-serializers-json/pom.xml
+++ b/streampipes-serializers-json/pom.xml
@@ -20,7 +20,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -31,12 +31,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -49,7 +49,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-test-utils</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/streampipes-service-base/pom.xml b/streampipes-service-base/pom.xml
index 41e0ddf..4c5811a 100644
--- a/streampipes-service-base/pom.xml
+++ b/streampipes-service-base/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-commons</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-discovery</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-service-discovery-api/pom.xml b/streampipes-service-discovery-api/pom.xml
index 245242b..fd73b1d 100644
--- a/streampipes-service-discovery-api/pom.xml
+++ b/streampipes-service-discovery-api/pom.xml
@@ -17,13 +17,11 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/streampipes-service-discovery-consul/pom.xml b/streampipes-service-discovery-consul/pom.xml
index 0561614..2d79d0e 100644
--- a/streampipes-service-discovery-consul/pom.xml
+++ b/streampipes-service-discovery-consul/pom.xml
@@ -17,13 +17,11 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -33,17 +31,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-logging</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-serializers-json</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-discovery-api</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- third-party dependencies -->
diff --git a/streampipes-service-discovery/pom.xml b/streampipes-service-discovery/pom.xml
index f3f3ff9..b4a26be 100644
--- a/streampipes-service-discovery/pom.xml
+++ b/streampipes-service-discovery/pom.xml
@@ -17,13 +17,11 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -33,12 +31,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-discovery-api</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-discovery-consul</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/streampipes-service-extensions-base/pom.xml b/streampipes-service-extensions-base/pom.xml
index 98c4ce6..5570442 100644
--- a/streampipes-service-extensions-base/pom.xml
+++ b/streampipes-service-extensions-base/pom.xml
@@ -17,13 +17,11 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -33,17 +31,17 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-container</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-base</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/client/StreamPipesClientRuntimeConnectionResolver.java b/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/client/StreamPipesClientRuntimeConnectionResolver.java
index e9bf03b..52cf1b5 100644
--- a/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/client/StreamPipesClientRuntimeConnectionResolver.java
+++ b/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/client/StreamPipesClientRuntimeConnectionResolver.java
@@ -20,15 +20,16 @@
 import org.apache.streampipes.client.credentials.CredentialsProvider;
 import org.apache.streampipes.client.credentials.StreamPipesTokenCredentials;
 import org.apache.streampipes.client.model.ClientConnectionUrlResolver;
-import org.apache.streampipes.commons.constants.Envs;
 import org.apache.streampipes.commons.constants.DefaultEnvValues;
+import org.apache.streampipes.commons.constants.Envs;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.commons.networking.Networking;
-import org.apache.streampipes.service.base.BaseNetworkingConfig;
 import org.apache.streampipes.svcdiscovery.SpServiceDiscovery;
 import org.apache.streampipes.svcdiscovery.api.model.DefaultSpServiceGroups;
 import org.apache.streampipes.svcdiscovery.api.model.DefaultSpServiceTags;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 import java.net.UnknownHostException;
 import java.util.Collections;
 import java.util.List;
@@ -47,7 +48,7 @@
   }
 
   @Override
-  public String getBaseUrl() {
+  public String getBaseUrl() throws SpRuntimeException {
     List<String> baseUrls = findClientServices();
     if (baseUrls.size() > 0) {
       if (Envs.SP_DEBUG.exists()) {
diff --git a/streampipes-sources/pom.xml b/streampipes-sources/pom.xml
index a90de6d..6624b6c 100644
--- a/streampipes-sources/pom.xml
+++ b/streampipes-sources/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<groupId>org.apache.streampipes</groupId>
 		<artifactId>streampipes-parent</artifactId>
-		<version>0.70.0-SNAPSHOT</version>
+		<version>0.71.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>streampipes-sources</artifactId>
@@ -31,7 +31,7 @@
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-container</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 	</dependencies>
 </project>
\ No newline at end of file
diff --git a/streampipes-storage-api/pom.xml b/streampipes-storage-api/pom.xml
index 64d5248..2b0aa0c 100644
--- a/streampipes-storage-api/pom.xml
+++ b/streampipes-storage-api/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>streampipes-storage-api</artifactId>
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IDataLakeStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IDataLakeStorage.java
index d16cfc2..25159f0 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IDataLakeStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IDataLakeStorage.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.storage.api;
 
+import org.apache.streampipes.model.datalake.DataExplorerWidgetModel;
 import org.apache.streampipes.model.datalake.DataLakeMeasure;
 
 import java.util.List;
@@ -27,4 +28,8 @@
     boolean storeDataLakeMeasure(DataLakeMeasure measure);
 
     List<DataLakeMeasure> getAllDataLakeMeasures();
+
+    DataLakeMeasure findOne(String id);
+
+    void updateDataLakeMeasure(DataLakeMeasure measure);
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/ErrorMessageLd.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
similarity index 60%
rename from streampipes-model/src/main/java/org/apache/streampipes/model/ErrorMessageLd.java
rename to streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
index 091f35b..b74bbc5 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/ErrorMessageLd.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
@@ -16,25 +16,23 @@
  *
  */
 
-package org.apache.streampipes.model;
+package org.apache.streampipes.storage.api;
 
+import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 
-public class ErrorMessageLd extends MessageLd {
+public interface IGenericStorage {
 
-	public ErrorMessageLd() {
-		super(false);
-	}
+  List<Map<String, Object>> findAll(String type) throws IOException;
 
-	public ErrorMessageLd(NotificationLd...notifications) {
-		super(false, notifications);
-	}
+  Map<String, Object> findOne(String id) throws IOException;
 
-	public ErrorMessageLd(List<NotificationLd> notifications) {
-		super(false, notifications.toArray(new NotificationLd[0]));
-	}
+  Map<String, Object> create(String payload) throws IOException;
 
-	public ErrorMessageLd(String elementName, List<NotificationLd> notifications) {
-		super(false, notifications, elementName);
-	}
+  <T> T create(T payload, Class<T> targetClass) throws IOException;
+
+  Map<String, Object> update(String id, String payload) throws IOException;
+
+  void delete(String id, String rev) throws IOException;
 }
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
index 5c52dbc..6b4af15 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
@@ -19,6 +19,8 @@
 
 public interface INoSqlStorage {
 
+  IGenericStorage getGenericStorage();
+
   IAdapterStorage getAdapterInstanceStorage();
 
   IAdapterStorage getAdapterDescriptionStorage();
diff --git a/streampipes-storage-couchdb/pom.xml b/streampipes-storage-couchdb/pom.xml
index dd4bf66..fcc41eb 100644
--- a/streampipes-storage-couchdb/pom.xml
+++ b/streampipes-storage-couchdb/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,22 +32,22 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-service-discovery</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-api</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
@@ -72,7 +72,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-test-utils</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
index 4a8b835..581ff22 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
@@ -30,6 +30,11 @@
   }
 
   @Override
+  public IGenericStorage getGenericStorage() {
+    return new GenericStorageImpl();
+  }
+
+  @Override
   public IAdapterStorage getAdapterInstanceStorage() {
     return new AdapterInstanceStorageImpl();
   }
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/constants/GenericCouchDbConstants.java
similarity index 74%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/constants/GenericCouchDbConstants.java
index a375af7..97a597e 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/constants/GenericCouchDbConstants.java
@@ -16,7 +16,12 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
-}
+package org.apache.streampipes.storage.couchdb.constants;
 
+public class GenericCouchDbConstants {
+
+  public static final String DESIGN_DOC_NAME = "appDocType";
+  public static final String VIEW_NAME = "appDocType";
+  public static final String DB_NAME = "genericstorage";
+
+}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/AdapterInstanceStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/AdapterInstanceStorageImpl.java
index da84fb8..ff6540b 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/AdapterInstanceStorageImpl.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/AdapterInstanceStorageImpl.java
@@ -58,7 +58,7 @@
     @Override
     public AdapterDescription getAdapter(String adapterId) {
         DbCommand<Optional<AdapterDescription>, AdapterDescription> cmd = new FindCommand<>(couchDbClientSupplier, adapterId, AdapterDescription.class);
-        return cmd.execute().get();
+        return cmd.execute().orElse(null);
     }
 
     @Override
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/DataLakeStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/DataLakeStorageImpl.java
index 60a7559..943638a 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/DataLakeStorageImpl.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/DataLakeStorageImpl.java
@@ -41,4 +41,14 @@
         List<DataLakeMeasure> dataLakeMeasures = findAll();
         return dataLakeMeasures;
     }
+
+    @Override
+    public DataLakeMeasure findOne(String id) {
+        return find(id).orElse(null);
+    }
+
+    @Override
+    public void updateDataLakeMeasure(DataLakeMeasure measure) {
+        update(measure);
+    }
 }
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
new file mode 100644
index 0000000..27606dd
--- /dev/null
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.storage.couchdb.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.net.UrlEscapers;
+import org.apache.http.client.fluent.Content;
+import org.apache.http.client.fluent.Request;
+import org.apache.streampipes.storage.api.IGenericStorage;
+import org.apache.streampipes.storage.couchdb.constants.GenericCouchDbConstants;
+import org.apache.streampipes.storage.couchdb.utils.Utils;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class GenericStorageImpl implements IGenericStorage {
+
+  private static final String ID = "id";
+  private static final String SLASH = "/";
+
+  private final TypeReference<Map<String,Object>> typeRef = new TypeReference<>() {};
+  private final ObjectMapper mapper;
+
+  public GenericStorageImpl() {
+    this.mapper = new ObjectMapper();
+    this.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+  }
+
+  @Override
+  public List<Map<String, Object>> findAll(String type) throws IOException {
+    String query = getDatabaseRoute() + "/_design/appDocType/_view/appDocType?" + UrlEscapers.urlPathSegmentEscaper().escape("startkey=[\"" + type + "\"]&endkey=[\"" + type + "\",{}]&include_docs=true");
+    Map<String, Object> queryResult = this.queryDocuments(query);
+
+    List<Map<String, Object>> rows = (List<Map<String, Object>>) queryResult.get("rows");
+    List<Map<String, Object>> result = new ArrayList<>();
+
+    for (Map<String, Object> row : rows) {
+      if (!((String) row.get(ID)).startsWith("_design")) {
+        result.add((Map<String, Object>) row.get("doc"));
+      }
+    }
+
+    return result;
+  }
+
+  @Override
+  public Map<String, Object> findOne(String id) throws IOException {
+    return this.queryDocuments(getDatabaseRoute() + SLASH + id);
+  }
+
+  @Override
+  public Map<String, Object> create(String payload) throws IOException {
+    Request req = Utils.postRequest(getDatabaseRoute(), payload);
+    Content content = executeAndReturnContent(req);
+
+    Map<String, Object> requestResult = deserialize(content.asString());
+    return this.findOne((String) requestResult.get(ID));
+  }
+
+  @Override
+  public <T> T create(T payload, Class<T> targetClass) throws IOException {
+    Map<String, Object> result = this.create(this.mapper.writeValueAsString(payload));
+    return this.mapper.convertValue(result, targetClass);
+  }
+
+  @Override
+  public Map<String, Object> update(String id, String payload) throws IOException {
+    Request req = Utils.putRequest(getDatabaseRoute() + SLASH + id, payload);
+    Content content = executeAndReturnContent(req);
+
+    Map<String, Object> requestResult = deserialize(content.asString());
+    return this.findOne((String) requestResult.get(ID));
+  }
+
+  @Override
+  public void delete(String id, String rev) throws IOException {
+    Request req = Utils.deleteRequest(getDatabaseRoute() + SLASH + id + "?rev=" + rev);
+    Content content = executeAndReturnContent(req);
+  }
+
+  private Map<String, Object> queryDocuments(String route) throws IOException {
+    Request req = Utils.getRequest(route);
+    Content content = executeAndReturnContent(req);
+
+    return deserialize(content.asString(StandardCharsets.UTF_8));
+  }
+
+  private Map<String, Object> deserialize(String payload) throws JsonProcessingException {
+
+    return mapper.readValue(payload, typeRef);
+  }
+
+  private Content executeAndReturnContent(Request req) throws IOException {
+    return req.execute().returnContent();
+  }
+
+  private String getDatabaseRoute() {
+    return Utils.getDatabaseRoute(GenericCouchDbConstants.DB_NAME);
+  }
+}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
index af208ac..311c55f 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
@@ -108,6 +108,7 @@
             .registerSubtype(UnitTransformRuleDescription.class, "org.apache.streampipes.model.UnitTransformRuleDescription")
             .registerSubtype(TimestampTranfsformationRuleDescription.class, "org.apache.streampipes.model.TimestampTranfsformationRuleDescription")
             .registerSubtype(EventRateTransformationRuleDescription.class, "org.apache.streampipes.model.EventRateTransformationRuleDescription")
+            .registerSubtype(ChangeDatatypeTransformationRuleDescription.class, "org.apache.streampipes.model.ChangeDatatypeTransformationRuleDescription")
             .registerSubtype(CorrectionValueTransformationRuleDescription.class, "org.apache.streampipes.model.CorrectionValueTransformationRuleDescription"));
 
     builder.registerTypeAdapterFactory(RuntimeTypeAdapterFactory.of(AdapterDescription.class, "type")
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/CouchDbViewGenerator.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/CouchDbViewGenerator.java
new file mode 100644
index 0000000..b9c4409
--- /dev/null
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/CouchDbViewGenerator.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.storage.couchdb.utils;
+
+import org.apache.http.client.fluent.Request;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+import static org.apache.streampipes.storage.couchdb.constants.GenericCouchDbConstants.*;
+
+public class CouchDbViewGenerator {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CouchDbViewGenerator.class);
+
+  public void createGenericDatabaseIfNotExists() {
+    LOG.info("Checking if generic database {} exists...", DB_NAME);
+
+    try {
+      int status = Request.Put(Utils.getDatabaseRoute(DB_NAME)).execute().returnResponse().getStatusLine().getStatusCode();
+
+      if (status == 201) {
+        LOG.info("Database {} successfully created", DB_NAME);
+        createViews();
+      } else if (status == 412) {
+        LOG.info("Database {} already present", DB_NAME);
+      } else {
+        LOG.warn("Status code {} from CouchDB - something went wrong during install!", status);
+      }
+    } catch (IOException e) {
+      LOG.error("Could not connect to CouchDB storage", e);
+    }
+  }
+
+  private void createViews() throws IOException {
+    LOG.info("Initializing database views...");
+
+    String viewContent = "{\n" +
+      "\"views\": {\n" +
+      "\"appDocType\": {\n" +
+      "\"map\": \"function (doc) {\\nif (doc._id) {\\nemit([doc.appDocType, doc._id], 1)\\n}\\n}\"\n" +
+      "}\n" +
+      "},\n" +
+      "\"language\": \"javascript\"\n" +
+      "}";
+
+    int status = Utils.putRequest(Utils.getDatabaseRoute(DB_NAME) + "/_design/" + DESIGN_DOC_NAME, viewContent)
+      .execute()
+      .returnResponse()
+      .getStatusLine()
+      .getStatusCode();
+
+    if (status == 201) {
+      LOG.info("View {} successfully created", VIEW_NAME);
+    } else {
+      LOG.warn("Status code {} from CouchDB - something went wrong during view generation!", status);
+    }
+  }
+}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
index 34a989a..d12e6e4 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
@@ -18,6 +18,8 @@
 
 package org.apache.streampipes.storage.couchdb.utils;
 
+import org.apache.http.client.fluent.Request;
+import org.apache.http.entity.ContentType;
 import org.apache.streampipes.storage.couchdb.serializer.GsonSerializer;
 import org.lightcouch.CouchDbClient;
 import org.lightcouch.CouchDbProperties;
@@ -180,12 +182,53 @@
     return new CouchDbClient(props(dbname));
   }
 
-  public static CouchDbClient getCoucbDbClient(String table) {
-    return new CouchDbClient(props(table));
+  public static CouchDbClient getCouchDbClient(String database) {
+    return new CouchDbClient(props(database));
   }
 
   private static CouchDbProperties props(String dbname) {
-    return new CouchDbProperties(dbname, true, CouchDbConfig.INSTANCE.getProtocol(),
-            CouchDbConfig.INSTANCE.getHost(), CouchDbConfig.INSTANCE.getPort(), null, null);
+    return new CouchDbProperties(
+      dbname,
+      true,
+      CouchDbConfig.INSTANCE.getProtocol(),
+      CouchDbConfig.INSTANCE.getHost(),
+      CouchDbConfig.INSTANCE.getPort(),
+      null,
+      null);
+  }
+
+  public static String getDatabaseRoute(String databaseName) {
+    return toUrl() + "/" + databaseName;
+  }
+
+  private static String toUrl() {
+    return CouchDbConfig.INSTANCE.getProtocol()
+      + "://" + CouchDbConfig.INSTANCE.getHost()
+      + ":" + CouchDbConfig.INSTANCE.getPort();
+  }
+
+  public static Request getRequest(String route) {
+    return append(Request.Get(route));
+  }
+
+  public static Request postRequest(String route,
+                                    String payload) {
+    return append(Request.Post(route).bodyString(payload, ContentType.APPLICATION_JSON));
+  }
+
+  public static Request deleteRequest(String route) {
+    return append(Request.Delete(route));
+  }
+
+  public static Request putRequest(String route,
+                                   String payload) {
+    return append(Request.Put(route).bodyString(payload, ContentType.APPLICATION_JSON));
+  }
+
+  private static Request append(Request req) {
+    req.connectTimeout(1000)
+      .socketTimeout(100000);
+
+    return req;
   }
 }
diff --git a/streampipes-storage-management/pom.xml b/streampipes-storage-management/pom.xml
index c9df714..c102948 100644
--- a/streampipes-storage-management/pom.xml
+++ b/streampipes-storage-management/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-api</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-couchdb</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/streampipes-test-utils/pom.xml b/streampipes-test-utils/pom.xml
index f1a48f1..0961a45 100644
--- a/streampipes-test-utils/pom.xml
+++ b/streampipes-test-utils/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,7 +32,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- Test dependencies -->
diff --git a/streampipes-user-management/pom.xml b/streampipes-user-management/pom.xml
index e3056e5..a9f6c65 100644
--- a/streampipes-user-management/pom.xml
+++ b/streampipes-user-management/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,22 +32,22 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-config</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-model-client</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-security-jwt</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-storage-management</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-vocabulary/pom.xml b/streampipes-vocabulary/pom.xml
index b6a9a2a..4850636 100644
--- a/streampipes-vocabulary/pom.xml
+++ b/streampipes-vocabulary/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/streampipes-wrapper-distributed/pom.xml b/streampipes-wrapper-distributed/pom.xml
index 66473cc..0aec356 100644
--- a/streampipes-wrapper-distributed/pom.xml
+++ b/streampipes-wrapper-distributed/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,22 +32,22 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-jms</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-kafka</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-messaging-mqtt</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/streampipes-wrapper-flink/pom.xml b/streampipes-wrapper-flink/pom.xml
index e976ee6..d30a26e 100644
--- a/streampipes-wrapper-flink/pom.xml
+++ b/streampipes-wrapper-flink/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.streampipes</groupId>
         <artifactId>streampipes-parent</artifactId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>streampipes-wrapper-flink</artifactId>
@@ -32,7 +32,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-distributed</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-wrapper-kafka-streams/pom.xml b/streampipes-wrapper-kafka-streams/pom.xml
index fa67897..f200b96 100644
--- a/streampipes-wrapper-kafka-streams/pom.xml
+++ b/streampipes-wrapper-kafka-streams/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,7 +32,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-distributed</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-wrapper-python/pom.xml b/streampipes-wrapper-python/pom.xml
index fee32e1..c41e6d2 100644
--- a/streampipes-wrapper-python/pom.xml
+++ b/streampipes-wrapper-python/pom.xml
@@ -20,7 +20,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/streampipes-wrapper-python/requirements.txt b/streampipes-wrapper-python/requirements.txt
index f5cd4b6..d029896 100644
--- a/streampipes-wrapper-python/requirements.txt
+++ b/streampipes-wrapper-python/requirements.txt
@@ -1,4 +1,4 @@
-waitress==2.1.1
+waitress==2.1.2
 click==7.1.2
 confluent-kafka==1.4.2
 Flask==1.1.2
diff --git a/streampipes-wrapper-python/setup.py b/streampipes-wrapper-python/setup.py
index 11f267f..ba40ffd 100644
--- a/streampipes-wrapper-python/setup.py
+++ b/streampipes-wrapper-python/setup.py
@@ -43,7 +43,7 @@
         'Flask==1.1.2',
         'flask-classful==0.14.2',
         'Flask-Negotiate==0.1.0',
-        'waitress==2.1.1',
+        'waitress==2.1.2',
         'python-consul==1.1.0'
     ],
     tests_require=[],
diff --git a/streampipes-wrapper-siddhi/pom.xml b/streampipes-wrapper-siddhi/pom.xml
index fa4e337..99f56c9 100644
--- a/streampipes-wrapper-siddhi/pom.xml
+++ b/streampipes-wrapper-siddhi/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
-        <version>0.70.0-SNAPSHOT</version>
+        <version>0.71.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -33,7 +33,7 @@
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-wrapper-standalone</artifactId>
-            <version>0.70.0-SNAPSHOT</version>
+            <version>0.71.0-SNAPSHOT</version>
         </dependency>
 
         <!-- External dependencies -->
diff --git a/streampipes-wrapper-standalone/pom.xml b/streampipes-wrapper-standalone/pom.xml
index b4b9286..8c005ca 100644
--- a/streampipes-wrapper-standalone/pom.xml
+++ b/streampipes-wrapper-standalone/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<groupId>org.apache.streampipes</groupId>
 		<artifactId>streampipes-parent</artifactId>
-		<version>0.70.0-SNAPSHOT</version>
+		<version>0.71.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>streampipes-wrapper-standalone</artifactId>
@@ -32,7 +32,7 @@
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-wrapper</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 	</dependencies>
 </project>
\ No newline at end of file
diff --git a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/routing/StandaloneSpInputCollector.java b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/routing/StandaloneSpInputCollector.java
index 47f0956..77277c6 100644
--- a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/routing/StandaloneSpInputCollector.java
+++ b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/routing/StandaloneSpInputCollector.java
@@ -49,11 +49,7 @@
   }
 
   private void send(RawDataProcessor rawDataProcessor, byte[] event) {
-    try {
       rawDataProcessor.process(dataFormatDefinition.toMap(event), topic);
-    } catch (SpRuntimeException e) {
-      e.printStackTrace();
-    }
   }
 
   @Override
diff --git a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneEventProcessorRuntime.java b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneEventProcessorRuntime.java
index 196b396..e297d47 100644
--- a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneEventProcessorRuntime.java
+++ b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneEventProcessorRuntime.java
@@ -27,13 +27,17 @@
 import org.apache.streampipes.wrapper.routing.SpOutputCollector;
 import org.apache.streampipes.wrapper.runtime.EventProcessor;
 import org.apache.streampipes.wrapper.standalone.manager.ProtocolManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.Map;
 import java.util.function.Supplier;
 
 public class StandaloneEventProcessorRuntime<B extends EventProcessorBindingParams> extends
-        StandalonePipelineElementRuntime<B, DataProcessorInvocation,
-                EventProcessorRuntimeParams<B>, EventProcessorRuntimeContext, EventProcessor<B>> {
+    StandalonePipelineElementRuntime<B, DataProcessorInvocation,
+        EventProcessorRuntimeParams<B>, EventProcessorRuntimeContext, EventProcessor<B>> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(StandaloneEventProcessorRuntime.class);
 
   public StandaloneEventProcessorRuntime(Supplier<EventProcessor<B>> supplier,
                                          EventProcessorRuntimeParams<B> params) {
@@ -43,18 +47,18 @@
 
   public SpOutputCollector getOutputCollector() throws SpRuntimeException {
     return ProtocolManager.findOutputCollector(
-            params
-                    .getBindingParams()
-                    .getGraph()
-                    .getOutputStream()
-                    .getEventGrounding()
-                    .getTransportProtocol(),
-            params.getBindingParams()
-                    .getGraph()
-                    .getOutputStream()
-                    .getEventGrounding()
-                    .getTransportFormats()
-                    .get(0));
+        params
+            .getBindingParams()
+            .getGraph()
+            .getOutputStream()
+            .getEventGrounding()
+            .getTransportProtocol(),
+        params.getBindingParams()
+            .getGraph()
+            .getOutputStream()
+            .getEventGrounding()
+            .getTransportFormats()
+            .get(0));
   }
 
   @Override
@@ -65,8 +69,12 @@
   }
 
   @Override
-  public void process(Map<String, Object> rawEvent, String sourceInfo) throws SpRuntimeException {
-    getEngine().onEvent(params.makeEvent(rawEvent, sourceInfo), getOutputCollector());
+  public void process(Map<String, Object> rawEvent, String sourceInfo) {
+    try {
+      engine.onEvent(params.makeEvent(rawEvent, sourceInfo), getOutputCollector());
+    } catch (RuntimeException e) {
+      LOG.error("RuntimeException while processing event in {}", engine.getClass().getCanonicalName(), e);
+    }
   }
 
   @Override
diff --git a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneEventSinkRuntime.java b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneEventSinkRuntime.java
index 75b0b8e..c1fd982 100644
--- a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneEventSinkRuntime.java
+++ b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneEventSinkRuntime.java
@@ -25,16 +25,20 @@
 import org.apache.streampipes.wrapper.params.runtime.EventSinkRuntimeParams;
 import org.apache.streampipes.wrapper.routing.SpInputCollector;
 import org.apache.streampipes.wrapper.runtime.EventSink;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.Map;
 import java.util.function.Supplier;
 
 public class StandaloneEventSinkRuntime<B extends EventSinkBindingParams> extends
-        StandalonePipelineElementRuntime<B, DataSinkInvocation,
-                EventSinkRuntimeParams<B>, EventSinkRuntimeContext, EventSink<B>> {
+    StandalonePipelineElementRuntime<B, DataSinkInvocation,
+        EventSinkRuntimeParams<B>, EventSinkRuntimeContext, EventSink<B>> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(StandaloneEventSinkRuntime.class);
 
   public StandaloneEventSinkRuntime(Supplier<EventSink<B>> supplier, EventSinkRuntimeParams<B>
-          params) {
+      params) {
     super(supplier, params);
   }
 
@@ -46,8 +50,12 @@
   }
 
   @Override
-  public void process(Map<String, Object> rawEvent, String sourceInfo) throws SpRuntimeException {
-    engine.onEvent(params.makeEvent(rawEvent, sourceInfo));
+  public void process(Map<String, Object> rawEvent, String sourceInfo) {
+    try {
+      engine.onEvent(params.makeEvent(rawEvent, sourceInfo));
+    } catch (RuntimeException e) {
+      LOG.error("RuntimeException while processing event in {}", engine.getClass().getCanonicalName() , e);
+    }
   }
 
   @Override
@@ -66,7 +74,7 @@
 
   @Override
   public void postDiscard() throws SpRuntimeException {
-    for(SpInputCollector spInputCollector : getInputCollectors()) {
+    for (SpInputCollector spInputCollector : getInputCollectors()) {
       spInputCollector.disconnect();
     }
   }
diff --git a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneExternalEventProcessorRuntime.java b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneExternalEventProcessorRuntime.java
index a2177f2..01c0187 100644
--- a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneExternalEventProcessorRuntime.java
+++ b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneExternalEventProcessorRuntime.java
@@ -42,7 +42,7 @@
   }
 
   @Override
-  public void process(Map<String, Object> rawEvent, String sourceInfo) throws SpRuntimeException {
+  public void process(Map<String, Object> rawEvent, String sourceInfo) {
 
   }
 
diff --git a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneExternalEventSinkRuntime.java b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneExternalEventSinkRuntime.java
index 3fb06e2..418702d 100644
--- a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneExternalEventSinkRuntime.java
+++ b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/runtime/StandaloneExternalEventSinkRuntime.java
@@ -41,7 +41,7 @@
   }
 
   @Override
-  public void process(Map<String, Object> rawEvent, String sourceInfo) throws SpRuntimeException {
+  public void process(Map<String, Object> rawEvent, String sourceInfo) {
 
   }
 
diff --git a/streampipes-wrapper/pom.xml b/streampipes-wrapper/pom.xml
index a02e8a9..45ecc38 100644
--- a/streampipes-wrapper/pom.xml
+++ b/streampipes-wrapper/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<groupId>org.apache.streampipes</groupId>
 		<artifactId>streampipes-parent</artifactId>
-		<version>0.70.0-SNAPSHOT</version>
+		<version>0.71.0-SNAPSHOT</version>
 	</parent>
 	<artifactId>streampipes-wrapper</artifactId>
 
@@ -30,32 +30,32 @@
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-container</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-service-extensions-base</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-client</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-dataformat</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.streampipes</groupId>
 			<artifactId>streampipes-messaging</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
 		</dependency>
         <dependency>
             <groupId>org.apache.streampipes</groupId>
             <artifactId>streampipes-sdk</artifactId>
-			<version>0.70.0-SNAPSHOT</version>
+			<version>0.71.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/routing/RawDataProcessor.java b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/routing/RawDataProcessor.java
index 648b9b5..bb4117c 100644
--- a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/routing/RawDataProcessor.java
+++ b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/routing/RawDataProcessor.java
@@ -17,11 +17,9 @@
  */
 package org.apache.streampipes.wrapper.routing;
 
-import org.apache.streampipes.commons.exceptions.SpRuntimeException;
-
 import java.util.Map;
 
 public interface RawDataProcessor {
 
-  void process(Map<String, Object> rawEvent, String sourceInfo) throws SpRuntimeException;
+  void process(Map<String, Object> rawEvent, String sourceInfo);
 }
diff --git a/ui/.gitignore b/ui/.gitignore
index fa76110..77e77f6 100644
--- a/ui/.gitignore
+++ b/ui/.gitignore
@@ -21,6 +21,7 @@
 
 # prebuild
 src/app/app-routing.module.ts
+src/app/app-overview/apps.ts
 src/app/appng5.module.ts
 src/app/home/home.service.ts
 src/app/services/version/version.service.ts
diff --git a/ui/cypress/fixtures/connect/schemaRules/expected.csv b/ui/cypress/fixtures/connect/schemaRules/expected.csv
index 38a8aeb..411fac9 100644
--- a/ui/cypress/fixtures/connect/schemaRules/expected.csv
+++ b/ui/cypress/fixtures/connect/schemaRules/expected.csv
@@ -1,2 +1,2 @@
-count;staticpropertyname;temperature
+count;staticPropertyName;temperature
 122.0;id1;11.0
diff --git a/ui/cypress/fixtures/datalake/sample.csv b/ui/cypress/fixtures/datalake/sample.csv
index 355a4a0..09d1490 100644
--- a/ui/cypress/fixtures/datalake/sample.csv
+++ b/ui/cypress/fixtures/datalake/sample.csv
@@ -1,11 +1,11 @@
 timestamp;randombool;randomnumber;randomtext
-1623871499055;true;62.0;c
-1623871500059;false;46.0;a
-1623871501064;true;41.0;b
-1623871502070;true;41.0;b
-1623871503078;false;22.0;b
-1623871504082;true;56.0;a
-1623871505084;false;77.0;b
-1623871506086;true;77.0;a
-1623871507091;true;85.0;b
-1623871508093;false;22.0;a
+1653871499055;true;62.0;c
+1653871500059;false;46.0;a
+1653871501064;true;41.0;b
+1653871502070;true;41.0;b
+1653871503078;false;22.0;b
+1653871504082;true;56.0;a
+1653871505084;false;77.0;b
+1653871506086;true;77.0;a
+1653871507091;true;85.0;b
+1653871508093;false;22.0;a
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/description.json b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/description.json
new file mode 100644
index 0000000..704e892
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/description.json
@@ -0,0 +1,20 @@
+{
+  "name": "math",
+  "config": [
+    {
+      "type": "drop-down",
+      "selector": "leftOperand",
+      "value": "temperature1"
+    },
+    {
+      "type": "drop-down",
+      "selector": "rightOperand",
+      "value": "temperature2"
+    },
+    {
+      "type": "radio",
+      "selector": "operation",
+      "value": "\\+"
+    }
+  ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/expected.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/expected.csv
new file mode 100644
index 0000000..5b481a5
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/expected.csv
@@ -0,0 +1,3 @@
+time;calculationResult;temperature1;temperature2
+1623871499055;5.0;2.0;3.0
+1623871500059;7.0;3.0;4.0
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/input.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/input.csv
new file mode 100644
index 0000000..1b75ffa
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math1/input.csv
@@ -0,0 +1,3 @@
+timestamp;temperature1;temperature2
+1623871499055;2;3
+1623871500059;3;4
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/description.json b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/description.json
new file mode 100644
index 0000000..7104559
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/description.json
@@ -0,0 +1,20 @@
+{
+  "name": "math",
+  "config": [
+    {
+      "type": "drop-down",
+      "selector": "leftOperand",
+      "value": "temperature1"
+    },
+    {
+      "type": "drop-down",
+      "selector": "rightOperand",
+      "value": "temperature2"
+    },
+    {
+      "type": "radio",
+      "selector": "operation",
+      "value": "\\/"
+    }
+  ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/expected.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/expected.csv
new file mode 100644
index 0000000..43a0779
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/expected.csv
@@ -0,0 +1,3 @@
+time;calculationResult;temperature1;temperature2
+1623871499055;1.0;4.0;4.0
+1623871500059;20.0;100.0;5.0
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/input.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/input.csv
new file mode 100644
index 0000000..aaad252
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math2/input.csv
@@ -0,0 +1,3 @@
+timestamp;temperature1;temperature2
+1623871499055;4;4
+1623871500059;100.0;5.0
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/description.json b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/description.json
new file mode 100644
index 0000000..968a447
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/description.json
@@ -0,0 +1,20 @@
+{
+  "name": "math",
+  "config": [
+    {
+      "type": "drop-down",
+      "selector": "leftOperand",
+      "value": "temperature1"
+    },
+    {
+      "type": "drop-down",
+      "selector": "rightOperand",
+      "value": "temperature2"
+    },
+    {
+      "type": "radio",
+      "selector": "operation",
+      "value": "\\*"
+    }
+  ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/expected.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/expected.csv
new file mode 100644
index 0000000..3f681d9
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/expected.csv
@@ -0,0 +1,3 @@
+time;calculationResult;temperature1;temperature2
+1623871499055;8.0;4.0;2.0
+1623871500059;17.5;3.5;5.0
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/input.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/input.csv
new file mode 100644
index 0000000..9e97f57
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/math3/input.csv
@@ -0,0 +1,3 @@
+timestamp;temperature1;temperature2
+1623871499055;4;2
+1623871500059;3.5;5.0
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/description.json b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/description.json
new file mode 100644
index 0000000..7416eea
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/description.json
@@ -0,0 +1,20 @@
+{
+  "name": "static_math",
+  "config": [
+    {
+      "type": "drop-down",
+      "selector": "leftOperand",
+      "value": "temperature1"
+    },
+    {
+      "type": "input",
+      "selector": "rightOperandValue",
+      "value": "5"
+    },
+    {
+      "type": "radio",
+      "selector": "operation",
+      "value": "\\*"
+    }
+  ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/expected.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/expected.csv
new file mode 100644
index 0000000..6727b72
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/expected.csv
@@ -0,0 +1,3 @@
+time;temperature1
+1623871499055;20.0
+1623871500059;17.5
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/input.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/input.csv
new file mode 100644
index 0000000..437bd65
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath1/input.csv
@@ -0,0 +1,3 @@
+timestamp;temperature1
+1623871499055;4
+1623871500059;3.5
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/description.json b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/description.json
new file mode 100644
index 0000000..948f842
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/description.json
@@ -0,0 +1,20 @@
+{
+  "name": "static_math",
+  "config": [
+    {
+      "type": "drop-down",
+      "selector": "leftOperand",
+      "value": "temperature1"
+    },
+    {
+      "type": "input",
+      "selector": "rightOperandValue",
+      "value": "1.5"
+    },
+    {
+      "type": "radio",
+      "selector": "operation",
+      "value": "\\/"
+    }
+  ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/expected.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/expected.csv
new file mode 100644
index 0000000..5a04b8a
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/expected.csv
@@ -0,0 +1,3 @@
+time;temperature1
+1623871499055;4.0
+1623871500059;2.0
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/input.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/input.csv
new file mode 100644
index 0000000..933646d
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/staticmath2/input.csv
@@ -0,0 +1,3 @@
+timestamp;temperature1
+1623871499055;6
+1623871500059;3
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/description.json b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/description.json
new file mode 100644
index 0000000..7edea59
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/description.json
@@ -0,0 +1,15 @@
+{
+  "name": "trigonometry_functions",
+  "config": [
+    {
+      "type": "drop-down",
+      "selector": "operand",
+      "value": "temperature1"
+    },
+    {
+      "type": "radio",
+      "selector": "operation",
+      "value": "sin"
+    }
+  ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/expected.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/expected.csv
new file mode 100644
index 0000000..bef8e92
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/expected.csv
@@ -0,0 +1,3 @@
+time;temperature1;trigonometryResult
+1623871499055;90.0;0.8939966636005579
+1623871500059;180.0;-0.8011526357338304
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/input.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/input.csv
new file mode 100644
index 0000000..13f6543
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry1/input.csv
@@ -0,0 +1,3 @@
+timestamp;temperature1
+1623871499055;90
+1623871500059;180.0
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/description.json b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/description.json
new file mode 100644
index 0000000..d8304c3
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/description.json
@@ -0,0 +1,15 @@
+{
+  "name": "trigonometry_functions",
+  "config": [
+    {
+      "type": "drop-down",
+      "selector": "operand",
+      "value": "temperature1"
+    },
+    {
+      "type": "radio",
+      "selector": "operation",
+      "value": "cos"
+    }
+  ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/expected.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/expected.csv
new file mode 100644
index 0000000..5ca7cff
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/expected.csv
@@ -0,0 +1,3 @@
+time;temperature1;trigonometryResult
+1623871499055;120.0;0.8141809705265618
+1623871500059;150.0;0.6992508064783751
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/input.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/input.csv
new file mode 100644
index 0000000..1de8e27
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/trigonometry2/input.csv
@@ -0,0 +1,3 @@
+timestamp;temperature1
+1623871499055;120
+1623871500059;150.0
diff --git a/ui/cypress/fixtures/pipelineElement/enrich-jvm/valueChange1/expected.csv b/ui/cypress/fixtures/pipelineElement/enrich-jvm/valueChange1/expected.csv
index deedcfc..55b0312 100644
--- a/ui/cypress/fixtures/pipelineElement/enrich-jvm/valueChange1/expected.csv
+++ b/ui/cypress/fixtures/pipelineElement/enrich-jvm/valueChange1/expected.csv
@@ -1,4 +1,4 @@
-time;ischanged;numberlist
+time;isChanged;numberlist
 1623871499055;false;2.0
 1623871500059;false;3.0
 1623871501064;true;4.0
diff --git a/ui/cypress/fixtures/pipelineElement/filters-jvm/thresholdDetection1/expected.csv b/ui/cypress/fixtures/pipelineElement/filters-jvm/thresholdDetection1/expected.csv
index a4d4d84..52727c6 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-jvm/thresholdDetection1/expected.csv
+++ b/ui/cypress/fixtures/pipelineElement/filters-jvm/thresholdDetection1/expected.csv
@@ -1,4 +1,4 @@
-time;randomnumber;thresholddetected
+time;randomnumber;thresholdDetected
 1623871499055;62.0;true
 1623871500059;46.0;false
 1623871501064;41.0;false
diff --git a/ui/cypress/fixtures/pipelineElement/filters-siddhi/count1/description.json b/ui/cypress/fixtures/pipelineElement/filters-siddhi/count1/description.json
index 8c17a38..d7ff167 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-siddhi/count1/description.json
+++ b/ui/cypress/fixtures/pipelineElement/filters-siddhi/count1/description.json
@@ -8,6 +8,11 @@
       "value": "text"
     },
     {
+      "type": "drop-down",
+      "selector": "timestamp-mapping",
+      "value": "timestamp"
+    },
+    {
       "type": "radio",
       "selector": "scale",
       "value": "Seconds"
diff --git a/ui/cypress/fixtures/pipelineElement/filters-siddhi/count1/input.csv b/ui/cypress/fixtures/pipelineElement/filters-siddhi/count1/input.csv
index a9b2ad7..c9d251c 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-siddhi/count1/input.csv
+++ b/ui/cypress/fixtures/pipelineElement/filters-siddhi/count1/input.csv
@@ -1,4 +1,4 @@
 timestamp;text
 1623871499055;hello
 1623871503078;world
-1623871503079;hello
+1623871504079;hello
diff --git a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase1/description.json b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase1/description.json
index 6635a5f..dc722f6 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase1/description.json
+++ b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase1/description.json
@@ -12,7 +12,7 @@
       "value": "Increase"
     },
     {
-      "type": "input",
+      "type": "slider",
       "selector": "increase",
       "value": "100"
     },
diff --git a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase1/expected.csv b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase1/expected.csv
index b35c308..cf3cbf9 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase1/expected.csv
+++ b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase1/expected.csv
@@ -1,2 +1,2 @@
-time;sensorvalue
+time;sensorValue
 1623871503078;10.0
diff --git a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase2/description.json b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase2/description.json
index 6635a5f..dc722f6 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase2/description.json
+++ b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase2/description.json
@@ -12,7 +12,7 @@
       "value": "Increase"
     },
     {
-      "type": "input",
+      "type": "slider",
       "selector": "increase",
       "value": "100"
     },
diff --git a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/description.json b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/description.json
index 6635a5f..dc722f6 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/description.json
+++ b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/description.json
@@ -12,7 +12,7 @@
       "value": "Increase"
     },
     {
-      "type": "input",
+      "type": "slider",
       "selector": "increase",
       "value": "100"
     },
diff --git a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/expected.csv b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/expected.csv
index b35c308..cf3cbf9 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/expected.csv
+++ b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/expected.csv
@@ -1,2 +1,2 @@
-time;sensorvalue
+time;sensorValue
 1623871503078;10.0
diff --git a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/input.csv b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/input.csv
index 73ccb34..b881d67 100644
--- a/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/input.csv
+++ b/ui/cypress/fixtures/pipelineElement/filters-siddhi/increase3/input.csv
@@ -2,3 +2,4 @@
 1623871499055;1.0
 1623871503078;10
 1623871503085;11
+1623871503086;15
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter1/expected.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter1/expected.csv
index 715670f..550e14d 100644
--- a/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter1/expected.csv
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter1/expected.csv
@@ -1,4 +1,4 @@
-time;booleantocount;counter
+time;booleanToCount;counter
 1623871499055;true;1
 1623871502070;false;2
 1623871505084;true;3
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/description.json b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/description.json
new file mode 100644
index 0000000..81ca935
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/description.json
@@ -0,0 +1,15 @@
+{
+  "name": "boolean_counter",
+  "config": [
+    {
+      "type": "drop-down",
+      "selector": "field",
+      "value": "randomboolean"
+    },
+    {
+      "type": "radio",
+      "selector": "flank",
+      "value": "BOTH"
+    }
+  ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/expected.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/expected.csv
new file mode 100644
index 0000000..1eaabc8
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/expected.csv
@@ -0,0 +1,8 @@
+time;counter;randomboolean
+1623871501064;1;true
+1623871502070;2;false
+1623871503078;3;true
+1623871504082;4;false
+1623871505084;5;true
+1623871506086;6;false
+1623871507091;7;true
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/input.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/input.csv
new file mode 100644
index 0000000..691d574
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanCounter2/input.csv
@@ -0,0 +1,11 @@
+timestamp;randomboolean
+1623871499055;false
+1623871500059;false
+1623871501064;true
+1623871502070;false
+1623871503078;true
+1623871504082;false
+1623871505084;true
+1623871506086;false
+1623871507091;true
+1623871508093;true
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanInverter1/expected.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanInverter1/expected.csv
index 35eeb28..dae89b0 100644
--- a/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanInverter1/expected.csv
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/booleanInverter1/expected.csv
@@ -1,4 +1,4 @@
-time;booleantoinvert
+time;booleanToInvert
 1623871499055;false
 1623871500059;false
 1623871501064;false
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/countArray1/expected.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/countArray1/expected.csv
index 6d5dcbf..2f327e4 100644
--- a/ui/cypress/fixtures/pipelineElement/transformation-jvm/countArray1/expected.csv
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/countArray1/expected.csv
@@ -1,4 +1,4 @@
-time;countvalue
+time;countValue
 1623871499055;4.0
 1623871500059;2.0
 1623871507091;5.0
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/description.json b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/description.json
new file mode 100644
index 0000000..147ee23
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/description.json
@@ -0,0 +1,7 @@
+{
+ "name": "field_hasher",
+ "config": [
+   {"type":  "drop-down", "selector": "property-mapping", "value":  "sensorId"},
+   {"type":  "radio", "selector": "hash-algorithm", "value":  "SHA1"}
+ ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/expected.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/expected.csv
new file mode 100644
index 0000000..27830ff
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/expected.csv
@@ -0,0 +1,3 @@
+time;sensorId
+1623871499055;a9993e364706816aba3e25717850c26c9cd0d89d
+1623871500059;40bd001563085fc35165329ea1ff5c5ecbdbbeef
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/input.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/input.csv
new file mode 100644
index 0000000..bcbd541
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher1/input.csv
@@ -0,0 +1,3 @@
+timestamp;sensorId
+1623871499055;abc
+1623871500059;123
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/description.json b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/description.json
new file mode 100644
index 0000000..75aff69
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/description.json
@@ -0,0 +1,7 @@
+{
+ "name": "field_hasher",
+ "config": [
+   {"type":  "drop-down", "selector": "property-mapping", "value":  "sensorId"},
+   {"type":  "radio", "selector": "hash-algorithm", "value":  "MD5"}
+ ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/expected.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/expected.csv
new file mode 100644
index 0000000..8f61632
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/expected.csv
@@ -0,0 +1,3 @@
+time;sensorId
+1623871499055;900150983cd24fb0d6963f7d28e17f72
+1623871500059;202cb962ac59075b964b07152d234b70
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/input.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/input.csv
new file mode 100644
index 0000000..3f2fd76
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldHasher2/input.csv
@@ -0,0 +1,5 @@
+timestamp;sensorId
+1623871499055;abc
+1623871500059;123
+
+
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/description.json b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/description.json
new file mode 100644
index 0000000..40a5298
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/description.json
@@ -0,0 +1,8 @@
+{
+ "name": "field_mapper",
+ "config": [
+   {"type":  "checkbox", "selector": "value1", "value":  "check"},
+   {"type":  "checkbox", "selector": "value2", "value":  "check"},
+   {"type":  "input", "selector": "fieldName", "value":  "hashedField"}
+ ]
+}
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/expected.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/expected.csv
new file mode 100644
index 0000000..cc037c0
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/expected.csv
@@ -0,0 +1,3 @@
+time;hashedField
+1623871499055;e80b5017098950fc58aad83c8c14978e
+1623871500059;e10adc3949ba59abbe56e057f20f883e
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/input.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/input.csv
new file mode 100644
index 0000000..3808251
--- /dev/null
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/fieldMapper1/input.csv
@@ -0,0 +1,5 @@
+timestamp;value1;value2
+1623871499055;abc;def
+1623871500059;123;456
+
+
diff --git a/ui/cypress/fixtures/pipelineElement/transformation-jvm/signalEdgeFilter1/expected.csv b/ui/cypress/fixtures/pipelineElement/transformation-jvm/signalEdgeFilter1/expected.csv
index 48599eb..71be1ef 100644
--- a/ui/cypress/fixtures/pipelineElement/transformation-jvm/signalEdgeFilter1/expected.csv
+++ b/ui/cypress/fixtures/pipelineElement/transformation-jvm/signalEdgeFilter1/expected.csv
@@ -1,4 +1,4 @@
-time;booleanedge
+time;booleanEdge
 1623871499055;true
 1623871502070;false
 1623871505084;true
diff --git a/ui/cypress/support/model/UserInputType.ts b/ui/cypress/support/model/UserInputType.ts
index 694b84c..0938fd5 100644
--- a/ui/cypress/support/model/UserInputType.ts
+++ b/ui/cypress/support/model/UserInputType.ts
@@ -25,5 +25,6 @@
     'code-input' |
     'click' |
     'button' |
+    'slider' |
     'select';
 
diff --git a/ui/cypress/support/utils/ConnectEventSchemaUtils.ts b/ui/cypress/support/utils/ConnectEventSchemaUtils.ts
index c39da21..a9044a6 100644
--- a/ui/cypress/support/utils/ConnectEventSchemaUtils.ts
+++ b/ui/cypress/support/utils/ConnectEventSchemaUtils.ts
@@ -19,7 +19,7 @@
 export class ConnectEventSchemaUtils {
 
   public static markPropertyAsDimension(propertyName: string) {
-    cy.dataCy('property-scope-' + propertyName)
+    cy.dataCy('property-scope-' + propertyName, { timeout: 10000 })
       .click()
       .get('.mat-option-text')
       .contains('Dimension')
@@ -119,6 +119,7 @@
     // validate that static value is persisted
     cy.dataCy('edit-' + propertyName, { timeout: 10000 }).click({ force: true });
     cy.dataCy('connect-change-runtime-type', { timeout: 10000 }).contains(dataType);
+    cy.wait(1000);
     cy.dataCy('sp-save-edit-property').click();
   }
   public static eventSchemaNextBtnDisabled() {
diff --git a/ui/cypress/support/utils/ConnectUtils.ts b/ui/cypress/support/utils/ConnectUtils.ts
index becfa72..dc8c390 100644
--- a/ui/cypress/support/utils/ConnectUtils.ts
+++ b/ui/cypress/support/utils/ConnectUtils.ts
@@ -32,6 +32,8 @@
 
     ConnectUtils.goToConnect();
 
+    ConnectUtils.goToNewAdapterPage();
+
     ConnectUtils.selectAdapter(adapterConfiguration.adapterType);
 
     ConnectUtils.configureAdapter(adapterConfiguration.adapterConfiguration);
@@ -72,6 +74,8 @@
   private static addGenericAdapter(adapterConfiguration: GenericAdapterInput) {
     ConnectUtils.goToConnect();
 
+    ConnectUtils.goToNewAdapterPage();
+
     ConnectUtils.selectAdapter(adapterConfiguration.adapterType);
 
     ConnectUtils.configureAdapter(adapterConfiguration.protocolConfiguration);
@@ -90,16 +94,24 @@
     ConnectEventSchemaUtils.finishEventSchemaConfiguration();
   }
 
-  public static addMachineDataSimulator(name: string) {
+  public static addMachineDataSimulator(name: string, persist: boolean = false) {
 
-    const configuration = SpecificAdapterBuilder
+    const builder = SpecificAdapterBuilder
       .create('Machine_Data_Simulator')
       .setName(name)
-      .addInput('input', 'wait-time-ms', '1000')
-      .build();
+      .addInput('input', 'wait-time-ms', '1000');
+
+    if (persist) {
+      builder.setTimestampProperty('timestamp').
+                setStoreInDataLake();
+    }
+
+    const configuration = builder.build();
 
     ConnectUtils.goToConnect();
 
+    ConnectUtils.goToNewAdapterPage();
+
     ConnectUtils.selectAdapter(configuration.adapterType);
 
     ConnectUtils.configureAdapter(configuration.adapterConfiguration);
@@ -114,13 +126,17 @@
     cy.visit('#/connect');
   }
 
+  public static goToNewAdapterPage() {
+    cy.dataCy('connect-create-new-adapter-button').click();
+  }
+
   public static selectAdapter(name) {
     // Select adapter
     cy.get('#' + name).click();
   }
 
   public static configureAdapter(configs: UserInput[]) {
-
+    cy.wait(2000);
     StaticPropertyUtils.input(configs);
 
     // Next Button should not be disabled
@@ -185,13 +201,11 @@
     // Delete adapter
     cy.visit('#/connect');
 
-    cy.get('div').contains('My Adapters').parent().click();
-    cy.dataCy('delete').should('have.length', 1);
-    cy.dataCy('delete').click();
+    cy.dataCy('delete-adapter').should('have.length', 1);
     cy.dataCy('delete-adapter').click();
+    cy.dataCy('delete-adapter-confirmation').click();
     cy.dataCy('adapter-deletion-in-progress', { timeout: 10000 }).should('be.visible');
-    cy.dataCy('delete', { timeout: 20000 }).should('have.length', 0);
-    // });
+    cy.dataCy('delete-adapter', { timeout: 20000 }).should('have.length', 0);
   }
 
   public static setUpPreprocessingRuleTest(): AdapterInput {
@@ -207,6 +221,7 @@
 
 
     ConnectUtils.goToConnect();
+    ConnectUtils.goToNewAdapterPage();
     ConnectUtils.selectAdapter(adapterConfiguration.adapterType);
     ConnectUtils.configureAdapter(adapterConfiguration.protocolConfiguration);
     ConnectUtils.configureFormat(adapterConfiguration);
@@ -227,7 +242,7 @@
     cy.wait(10000);
 
     DataLakeUtils.checkResults(
-        'adaptertotestrules',
+        'Adapter to test rules',
         expectedFile,
         ignoreTime);
   }
diff --git a/ui/cypress/support/utils/DataLakeUtils.ts b/ui/cypress/support/utils/DataLakeUtils.ts
index 39b29cd..9596f38 100644
--- a/ui/cypress/support/utils/DataLakeUtils.ts
+++ b/ui/cypress/support/utils/DataLakeUtils.ts
@@ -65,7 +65,7 @@
     DataLakeUtils.selectTimeRange(
         new Date(2020, 10, 20, 22, 44),
         new Date(2021, 10, 20, 22, 44));
-    DataLakeUtils.addNewWidget();
+    // DataLakeUtils.addNewWidget();
     DataLakeUtils.selectDataSet(dataSet);
     DataLakeUtils.dataConfigSelectAllFields();
     DataLakeUtils.selectVisualizationConfig();
@@ -100,7 +100,6 @@
         .click();
 
     this.editDataView(name);
-    // cy.get('div').contains(name).parent().click();
 
   }
 
@@ -131,10 +130,8 @@
   public static saveAndReEditWidget(dataViewName: string) {
     // Save configuration
     DataLakeUtils.saveDataExplorerWidgetConfiguration();
-    DataLakeUtils.clickStartTab();
+    DataLakeUtils.goBackToOverview();
     DataLakeUtils.editDataView(dataViewName);
-    // Edit widget again
-    DataLakeUtils.editWidget('datalake_configuration');
   }
 
   public static clickTab(tabName: string) {
@@ -142,10 +139,13 @@
     cy.get('div').contains(tabName).parent().click();
   }
 
-  public static clickStartTab() {
-    this.clickTab('Start');
+
+  public static goBackToOverview() {
+    cy.dataCy('save-data-explorer-go-back-to-overview')
+        .click();
   }
 
+
   public static addNewWidget() {
     cy.dataCy('add-new-widget')
         .click();
@@ -168,7 +168,7 @@
     if (amountOfFilter === 0) {
       cy.dataCy('design-panel-data-settings-filter-field').should('not.exist');
     } else {
-      cy.dataCy('design-panel-data-settings-filter-field').should('be.visible');
+      cy.dataCy('design-panel-data-settings-filter-field', { timeout: 20000 }).should('be.visible');
     }
   }
 
@@ -245,8 +245,7 @@
   }
 
   public static goToDatalakeConfiguration() {
-    cy.visit('#/configuration');
-    cy.get('div').contains('DataLake').parent().click();
+    cy.visit('#/configuration/datalake');
   }
 
   public static checkResults(dataLakeIndex: string, fileRoute: string, ignoreTime?: boolean) {
@@ -254,7 +253,7 @@
     // Validate result in datalake
     cy.request({
       method: 'GET',
-      url: `/streampipes-backend/api/v4/datalake/measurements/${dataLakeIndex}/download?format=csv`,
+      url: `/streampipes-backend/api/v4/datalake/measurements/${dataLakeIndex}/download?format=csv&delimiter=semicolon`,
       headers: {
         'content-type': 'application/octet-stream'
       },
diff --git a/ui/cypress/support/utils/PipelineUtils.ts b/ui/cypress/support/utils/PipelineUtils.ts
index d74522c..6e2d18e 100644
--- a/ui/cypress/support/utils/PipelineUtils.ts
+++ b/ui/cypress/support/utils/PipelineUtils.ts
@@ -49,7 +49,8 @@
 
   private static goToPipelineEditor() {
     // Go to StreamPipes editor
-    cy.visit('#/editor');
+    cy.visit('#/pipelines');
+    cy.dataCy('pipelines-navigate-to-editor').click();
   }
 
   private static selectDataStream(pipelineInput: PipelineInput) {
@@ -91,22 +92,24 @@
     cy.dataCy('sp-editor-pipeline-name').type(pipelineInput.pipelineName);
     cy.dataCy('sp-editor-checkbox-start-immediately').children().click();
     cy.dataCy('sp-editor-save').click();
-    cy.dataCy('sp-pipeline-started-dialog', { timeout: 10000 }).should('be.visible');
-    cy.dataCy('sp-pipeline-dialog-close', { timeout: 10000 }).click();
+    cy.dataCy('sp-pipeline-started-dialog', { timeout: 15000 }).should('be.visible');
+    cy.dataCy('sp-pipeline-dialog-close', { timeout: 15000 }).click();
   }
 
 
   public static checkAmountOfPipelinesPipeline(amount: number) {
     cy.visit('#/pipelines');
-    cy.dataCy('delete').should('have.length', amount);
+    cy.dataCy('delete-pipeline').should('have.length', amount);
   }
 
   public static deletePipeline() {
     // Delete pipeline
     cy.visit('#/pipelines');
-    cy.dataCy('delete').should('have.length', 1);
-    cy.dataCy('delete').click({ force: true });
+    cy.dataCy('delete-pipeline').should('have.length', 1);
+    cy.dataCy('delete-pipeline').click({ force: true });
+
     cy.dataCy('sp-pipeline-stop-and-delete').click();
-    cy.dataCy('delete', { timeout: 10000 }).should('have.length', 0);
+
+    cy.dataCy('delete-pipeline', { timeout: 10000 }).should('have.length', 0);
   }
 }
diff --git a/ui/cypress/support/utils/StaticPropertyUtils.ts b/ui/cypress/support/utils/StaticPropertyUtils.ts
index a8d9f35..e3e730d 100644
--- a/ui/cypress/support/utils/StaticPropertyUtils.ts
+++ b/ui/cypress/support/utils/StaticPropertyUtils.ts
@@ -33,14 +33,16 @@
       } else if (config.type === 'radio') {
         cy.dataCy(config.selector.replace(' ', '_').toLowerCase() + '-' + config.value.replace(' ', '_').toLowerCase()).click();
       } else if (config.type === 'click') {
-        cy.dataCy(config.selector).click({ force: true });
+        cy.dataCy(config.selector).click({force: true});
       } else if (config.type === 'code-input') {
         cy.dataCy('reset-code-' + config.selector).click();
         cy.dataCy('code-editor-' + config.selector).type(config.value);
       } else if (config.type === 'input') {
-          cy.dataCy(config.selector).type(config.value).blur();
-        } else {
-          cy.dataCy(config.selector).type(config.value);
+        cy.dataCy(config.selector).clear().type(config.value).blur();
+      } else if (config.type === 'slider') {
+        cy.dataCy(config.selector).type(config.value);
+      } else {
+        cy.dataCy(config.selector).type(config.value);
       }
     });
   }
diff --git a/ui/cypress/support/utils/UserUtils.ts b/ui/cypress/support/utils/UserUtils.ts
index 8dd2754..c816ca6 100644
--- a/ui/cypress/support/utils/UserUtils.ts
+++ b/ui/cypress/support/utils/UserUtils.ts
@@ -28,13 +28,8 @@
       .addRole(UserRole.ROLE_ADMIN)
       .build();
 
-
-  // public static testUserName = 'admin@streampipes.apache.org';
-  // public static testUserPassword = 'admin';
-
   public static goToUserConfiguration() {
-    cy.visit('#/configuration');
-    cy.get('div').contains('Security').parent().click();
+    cy.visit('#/configuration/security');
   }
 
   public static addUser(user: User) {
diff --git a/ui/cypress/tests/adapter/opcAdapter.ts b/ui/cypress/tests/adapter/opcAdapter.ts
index 74ad8ba..8ec8e54 100644
--- a/ui/cypress/tests/adapter/opcAdapter.ts
+++ b/ui/cypress/tests/adapter/opcAdapter.ts
@@ -47,7 +47,7 @@
 
 const getAdapterBuilder = (pullMode: boolean) => {
 
-  const host: string = ParameterUtils.get('ipe-girlitz.fzi.de', 'opcua');
+  const host: string = ParameterUtils.get('localhost', 'opcua');
 
   const builder = SpecificAdapterBuilder
     .create('OPC_UA')
diff --git a/ui/cypress/tests/dashboard/dashboardTest.smoke.spec.ts b/ui/cypress/tests/dashboard/dashboardTest.smoke.spec.ts
index dd8eabf..be6ad80 100644
--- a/ui/cypress/tests/dashboard/dashboardTest.smoke.spec.ts
+++ b/ui/cypress/tests/dashboard/dashboardTest.smoke.spec.ts
@@ -17,31 +17,15 @@
  */
 
 import { ConnectUtils } from '../../support/utils/ConnectUtils';
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
-import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
-import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
 import { DashboardUtils } from '../../support/utils/DashboardUtils';
 
-const adapterName = 'simulator';
-
-
 describe('Test live dashboard', () => {
   beforeEach('Setup Test', () => {
     cy.initStreamPipesTest();
-    ConnectUtils.addMachineDataSimulator(adapterName);
+    ConnectUtils.addMachineDataSimulator('simulator', true);
   });
 
   it('Perform Test', () => {
-    const pipelineName = 'DashboardPipeline';
-    const pipelineInput = PipelineBuilder.create(pipelineName)
-      .addSource(adapterName)
-      .addSink(
-        PipelineElementBuilder.create('data_lake')
-          .addInput('input', 'db_measurement', 'demo')
-          .build())
-      .build();
-
-    PipelineUtils.testPipeline(pipelineInput);
 
     DashboardUtils.goToDashboard();
 
@@ -49,7 +33,7 @@
     const dashboardName = 'testDashboard';
     DashboardUtils.addAndEditDashboard(dashboardName);
 
-    DashboardUtils.addWidget(pipelineName, 'raw');
+    DashboardUtils.addWidget('Persist_simulator', 'raw');
 
     // Validate that data is coming (at least 3 events)
     DashboardUtils.validateRawWidgetEvents(3);
diff --git a/ui/cypress/tests/datalake/widgetDataConfiguration.smoke.spec.ts b/ui/cypress/tests/datalake/widgetDataConfiguration.smoke.spec.ts
index 4dab10a..a97e5d3 100644
--- a/ui/cypress/tests/datalake/widgetDataConfiguration.smoke.spec.ts
+++ b/ui/cypress/tests/datalake/widgetDataConfiguration.smoke.spec.ts
@@ -25,6 +25,9 @@
   beforeEach('Setup Test', () => {
     cy.initStreamPipesTest();
     DataLakeUtils.loadDataIntoDataLake('datalake/sample.csv');
+    // cy.login();
+    // DataLakeUtils.goToDatalake();
+
   });
 
   it('Perform Test', () => {
@@ -82,6 +85,7 @@
     /**
      * Test groupBy configuration and if it is persisted correctly
      */
+    cy.wait(1000);
     DataLakeUtils.clickGroupBy('randomtext');
     cy.wait(1000);
     cy.dataCy('data-explorer-table-row-randomtext', { timeout: 10000 }).first({ timeout: 10000 }).contains('a', { timeout: 10000 });
diff --git a/ui/cypress/tests/experimental/testJvmArchetype/.env b/ui/cypress/tests/experimental/testJvmArchetype/.env
index 1b8ff24..0330973 100644
--- a/ui/cypress/tests/experimental/testJvmArchetype/.env
+++ b/ui/cypress/tests/experimental/testJvmArchetype/.env
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-SP_VERSION=0.70.0-SNAPSHOT
+SP_VERSION=0.70.0
 SP_DOCKER_REGISTRY=apachestreampipes
 SP_SUBNET=172.31.0.0/16
 SP_CONSUL_CONTAINER_IP=172.31.0.9
diff --git a/ui/cypress/tests/experimental/testJvmArchetype/backend/.env b/ui/cypress/tests/experimental/testJvmArchetype/backend/.env
index 1b8ff24..0330973 100644
--- a/ui/cypress/tests/experimental/testJvmArchetype/backend/.env
+++ b/ui/cypress/tests/experimental/testJvmArchetype/backend/.env
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-SP_VERSION=0.70.0-SNAPSHOT
+SP_VERSION=0.70.0
 SP_DOCKER_REGISTRY=apachestreampipes
 SP_SUBNET=172.31.0.0/16
 SP_CONSUL_CONTAINER_IP=172.31.0.9
diff --git a/ui/cypress/tests/experimental/testJvmArchetype/testArchetype.sh b/ui/cypress/tests/experimental/testJvmArchetype/testArchetype.sh
index e365b18..7e77f97 100755
--- a/ui/cypress/tests/experimental/testJvmArchetype/testArchetype.sh
+++ b/ui/cypress/tests/experimental/testJvmArchetype/testArchetype.sh
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 mvn archetype:generate -DarchetypeGroupId=org.apache.streampipes \
-	-DarchetypeArtifactId=streampipes-archetype-extensions-jvm -DarchetypeVersion=0.70.0-SNAPSHOT \
+	-DarchetypeArtifactId=streampipes-archetype-extensions-jvm -DarchetypeVersion=0.70.0 \
 	-DgroupId=org.streampipes.test -DartifactId=automated-test -DclassNamePrefix=AutomatedTest -DpackageName=test -DinteractiveMode=false
 
 cd automated-test
diff --git a/ui/cypress/tests/pipelineElement/SinglePipelineElement.ts b/ui/cypress/tests/pipelineElement/SinglePipelineElement.ts
index 635d222..4fbb135 100644
--- a/ui/cypress/tests/pipelineElement/SinglePipelineElement.ts
+++ b/ui/cypress/tests/pipelineElement/SinglePipelineElement.ts
@@ -22,7 +22,7 @@
 const allTests = Cypress.env('processingElements');
 
 allTests.forEach(test => {
-  const testNames = ['countArray1'];
+  const testNames = ['staticmath1'];
 
   const processorTest = test as ProcessorTest;
 
diff --git a/ui/cypress/tests/thirdparty/MySQLDb.ts b/ui/cypress/tests/thirdparty/MySQLDb.ts
deleted file mode 100644
index ac661ba..0000000
--- a/ui/cypress/tests/thirdparty/MySQLDb.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { SpecificAdapterBuilder } from '../../support/builder/SpecificAdapterBuilder';
-import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
-import { ThirdPartyIntegrationUtils } from '../../support/utils/ThirdPartyIntegrationUtils';
-import { PipelineElementInput } from '../../support/model/PipelineElementInput';
-import { ParameterUtils } from '../../support/utils/ParameterUtils';
-
-describe('Test MySQL Integration', () => {
-  beforeEach('Setup Test', () => {
-    cy.initStreamPipesTest();
-  });
-
-  it('Perform Test', () => {
-    const dbName = 'cypressDatabase';
-    const host: string = ParameterUtils.get('localhost', 'mysql');
-
-    const sink: PipelineElementInput = PipelineElementBuilder.create('mysql_database')
-      .addInput('input', 'host', host)
-      .addInput('input', 'user', 'root')
-      .addInput('input', 'password', '7uc4rAymrPhxv6a5')
-      .addInput('input', 'db', 'sp')
-      .addInput('input', 'table', dbName)
-      .build();
-
-    const adapter = SpecificAdapterBuilder
-      .create('MySql_Stream_Adapter')
-      .setName('MySQL Adapter')
-      .setTimestampProperty('timestamp')
-      .addInput('input', 'mysqlHost', host)
-      .addInput('input', 'mysqlUser', 'root')
-      .addInput('input', 'mysqlPassword', '7uc4rAymrPhxv6a5')
-      .addInput('input', 'mysqlDatabase', 'sp')
-      .addInput('input', 'mysqlTable', dbName)
-      .build();
-
-    ThirdPartyIntegrationUtils.runTest(sink, adapter);
-  });
-
-});
diff --git a/ui/deployment/app-routing.module.mst b/ui/deployment/app-routing.module.mst
index 8994a2f..093d7a5 100644
--- a/ui/deployment/app-routing.module.mst
+++ b/ui/deployment/app-routing.module.mst
@@ -22,7 +22,6 @@
 import {LoginComponent} from "./login/components/login/login.component";
 import {SetupComponent} from "./login/components/setup/setup.component";
 import {StreampipesComponent} from "./core/components/streampipes/streampipes.component";
-import {PipelineDetailsComponent} from "./pipeline-details/pipeline-details.component";
 import {StandaloneDashboardComponent} from "./dashboard/components/standalone/standalone-dashboard.component";
 import {AuthCanActivateChildrenGuard} from "./_guards/auth.can-activate-children.guard";
 import {ConfiguredCanActivateGuard} from "./_guards/configured.can-activate.guard";
@@ -42,9 +41,9 @@
 import { ActivateAccountComponent } from './login/components/activate-account/activate-account.component';
 
 {{#modulesActive}}
-{{#ng5}}
+{{#componentImport}}
 import { {{{ng5_component}}} } from '{{{ng5_componentPath}}}';
-{{/ng5}}
+{{/componentImport}}
 {{/modulesActive}}
 
 const routes: Routes = [
@@ -60,13 +59,16 @@
   { path: '', component: StreampipesComponent, children: [
       { path: '', component: HomeComponent, canActivate: [ConfiguredCanActivateGuard] },
       {{#modulesActive}}
-      {{#ng5}}
+      {{#componentImport}}
       { path: '{{{link}}}', component: {{{ng5_component}}}, data: { authPageNames: [{{{pageNames}}}]}},
-      {{/ng5}}
+      {{/componentImport}}
+      {{^componentImport}}
+      { path: '', data: { authPageNames: [{{{pageNames}}}]}, loadChildren: () => import('{{{path}}}').then(m => m.{{{ng5_moduleName}}})},
+      {{/componentImport}}
       {{/modulesActive}}
+
       { path: 'notifications', component: NotificationsComponent },
       { path: 'info', component: InfoComponent },
-      { path: 'pipeline-details', component: PipelineDetailsComponent },
       { path: 'profile', component: ProfileComponent},
     ], canActivateChild: [AuthCanActivateChildrenGuard, PageAuthGuard] }
 ];
diff --git a/ui/deployment/appng5.module.mst b/ui/deployment/appng5.module.mst
index f0d2471..d2352e3 100644
--- a/ui/deployment/appng5.module.mst
+++ b/ui/deployment/appng5.module.mst
@@ -39,9 +39,7 @@
 import { LOADING_BAR_CONFIG } from '@ngx-loading-bar/core';
 
 {{#modulesActive}}
-{{#ng5}}
 import { {{{ng5_moduleName}}} } from '{{{path}}}';
-{{/ng5}}
 {{/modulesActive}}
 
 import { NotificationModule } from './notifications/notifications.module';
@@ -80,9 +78,7 @@
         ServicesModule,
         ProfileModule,
         {{#modulesActive}}
-        {{#ng5}}
         {{{ng5_moduleName}}},
-        {{/ng5}}
         {{/modulesActive}}
     ],
     providers: [
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/deployment/apps.ts
similarity index 62%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/deployment/apps.ts
index 58ba04b..c049ded 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/deployment/apps.ts
@@ -16,3 +16,18 @@
  *
  */
 
+import { App } from './apps.model';
+
+export class AvailableAppsService {
+
+  public static apps: App[] = [
+    {
+      appName: 'Asset Dashboards',
+      appDescription: 'Monitor measurements of your assets by placing visualizations on an image of your asset.',
+      appId: 'asset-monitoring',
+      appLink: 'asset-monitoring',
+      appModuleLink: () =>
+        import('../app-asset-monitoring/app-asset-monitoring.module').then(m => m.AppAssetMonitoringModule)
+    }
+  ];
+}
diff --git a/ui/deployment/base-navigation.component.mst b/ui/deployment/base-navigation.component.mst
index 7922163..cb0005a 100644
--- a/ui/deployment/base-navigation.component.mst
+++ b/ui/deployment/base-navigation.component.mst
@@ -17,9 +17,10 @@
  */
 
 
-import {NavigationEnd, Router} from "@angular/router";
+import { NavigationEnd, Router } from '@angular/router';
 import { PageName } from '../../_enums/page-name.enum';
 import { AuthService } from '../../services/auth.service';
+import { AppConstants } from '../../services/app.constants';
 
 export abstract class BaseNavigationComponent {
 
@@ -67,7 +68,8 @@
 
 
   constructor(protected authService: AuthService,
-                protected router: Router) {
+              protected router: Router,
+              private appConstants: AppConstants) {
 
     }
 
@@ -81,7 +83,7 @@
       this.activePageName = this.getPageTitle(this.activePage);
       this.router.events.subscribe(event => {
         if (event instanceof NavigationEnd) {
-          this.activePage = event.url.replace('/', '');
+          this.activePage = event.url.split('/')[1];
           this.activePageName = this.getPageTitle(this.activePage);
         }
       });
@@ -93,7 +95,7 @@
 
     getPageTitle(path) {
       const allMenuItems = this.menu.concat(this.admin);
-      let currentTitle = 'StreamPipes';
+      let currentTitle = this.appConstants.APP_NAME;
       allMenuItems.forEach(m => {
         if (m.link === path) {
           currentTitle = m.title;
diff --git a/ui/deployment/dev/config.yml b/ui/deployment/dev/config.yml
index d134f44..dc1acdf 100644
--- a/ui/deployment/dev/config.yml
+++ b/ui/deployment/dev/config.yml
@@ -19,12 +19,12 @@
   logo-navigation: 'deployment/dev/img/logo-navigation.png'
   favicon: 'deployment/dev/img/favicon.png'
 modules:
-  - spEditor
   - spPipelines
   - spConnect
   - spDashboard
   - spDataExplorer
   - spAppOverview
   - spAdd
+  - spAssets
   - spFiles
   - spConfiguration
diff --git a/ui/deployment/modules.yml b/ui/deployment/modules.yml
index a63513e..8655b53 100644
--- a/ui/deployment/modules.yml
+++ b/ui/deployment/modules.yml
@@ -13,8 +13,23 @@
 # See the License for the specific language governing permissions and

 # limitations under the License.

 

+

+spAssets:

+  componentImport: False

+  ng5_moduleName: 'AssetsModule'

+  ng5_component: 'EditorComponent'

+  ng5_componentPath: './editor/editor.component'

+  path: './assets/assets.module'

+  link: 'assets'

+  url: '/editor/:pipeline'

+  title: 'Asset Management'

+  description: 'Manage assets which help assigning pipelines, dashboards and adapters to real-world objects such as machines and plants.'

+  icon: 'precision_manufacturing'

+  homeImage: ''

+  admin: true

+  pageNames: 'PageName.ASSETS'

 spEditor:

-  ng5: True

+  componentImport: True

   ng5_moduleName: 'EditorModule'

   ng5_component: 'EditorComponent'

   ng5_componentPath: './editor/editor.component'

@@ -28,7 +43,7 @@
   admin: false

   pageNames: 'PageName.PIPELINE_EDITOR'

 spConnect:

-  ng5: True

+  componentImport: False

   ng5_moduleName: 'ConnectModule'

   ng5_component: 'ConnectComponent'

   ng5_componentPath: './connect/connect.component'

@@ -42,7 +57,7 @@
   admin: False

   pageNames: 'PageName.CONNECT'

 spPipelines:

-  ng5: True

+  componentImport: False

   ng5_moduleName: 'PipelinesModule'

   ng5_component: 'PipelinesComponent'

   ng5_componentPath: './pipelines/pipelines.component'

@@ -56,7 +71,7 @@
   admin: False

   pageNames: 'PageName.PIPELINE_OVERVIEW'

 spAdd:

-  ng5: True

+  componentImport: False

   ng5_moduleName: 'AddModule'

   ng5_component: 'AddComponent'

   ng5_componentPath: './add/add.component'

@@ -70,10 +85,10 @@
   admin: True

   pageNames: 'PageName.INSTALL_PIPELINE_ELEMENTS'

 spConfiguration:

-  ng5: True

+  componentImport: False

   ng5_moduleName: 'ConfigurationModule'

-  ng5_component: 'ConfigurationComponent'

-  ng5_componentPath: './configuration/configuration.component'

+  ng5_component: 'GeneralConfigurationComponent'

+  ng5_componentPath: './configuration/general-configuration/general-configuration.component'

   path: './configuration/configuration.module'

   link: 'configuration'

   url: '/configuration'

@@ -84,12 +99,12 @@
   pageNames: 'PageName.SETTINGS'

   admin: True

 spAppOverview:

-  ng5: True

+  componentImport: False

   ng5_moduleName: 'AppOverviewModule'

   ng5_component: 'AppOverviewComponent'

   ng5_componentPath: './app-overview/app-overview.component'

   path: './app-overview/app-overview.module'

-  link: 'app-overview'

+  link: 'apps'

   url: '/apps'

   title: 'Apps'

   description: 'The app overview allows you to view and open additional StreamPipes plugins.'

@@ -98,7 +113,7 @@
   admin: false

   pageNames: 'PageName.APPS'

 spDashboard:

-  ng5: True

+  componentImport: False

   ng5_moduleName: 'DashboardModule'

   ng5_component: 'DashboardComponent'

   ng5_componentPath: './dashboard/dashboard.component'

@@ -112,7 +127,7 @@
   admin: false

   pageNames: 'PageName.DASHBOARD'

 spDataExplorer:

-  ng5: True

+  componentImport: False

   ng5_moduleName: 'DataExplorerModule'

   ng5_component: 'DataExplorerComponent'

   ng5_componentPath: './data-explorer/data-explorer.component'

@@ -126,7 +141,7 @@
   admin: false

   pageNames: 'PageName.DATA_EXPLORER'

 spFiles:

-  ng5: True

+  componentImport: False

   ng5_moduleName: 'FilesModule'

   ng5_component: 'FilesComponent'

   ng5_componentPath: './files/files.component'

diff --git a/ui/deployment/prebuild.js b/ui/deployment/prebuild.js
index f104a2e..0c1a81d 100644
--- a/ui/deployment/prebuild.js
+++ b/ui/deployment/prebuild.js
@@ -62,7 +62,7 @@
 for (let module of config.modules) {

     modulesActive['modulesActive'].push({

         module: module,

-        ng5: modules[module]['ng5'],

+        componentImport: modules[module]['componentImport'],

         ng1_templateUrl: modules[module]['ng1_templateUrl'],

         ng5_moduleName: modules[module]['ng5_moduleName'],

         ng5_component: modules[module]['ng5_component'],

@@ -77,7 +77,7 @@
         description: modules[module]['description'],

         homeImage: modules[module]['homeImage']

     });

-    console.log('Active Angular ' + (modules[module]['ng5']===true?5:1) + ' Module: ' + module);

+    console.log('Active Angular Module: ' + module);

 }

 

 // Create necessary JavaScript-Files from Template and move to respective Directory

@@ -85,6 +85,7 @@
 fs.writeFileSync('src/app/home/home.service.ts', mustache.render(fs.readFileSync('deployment/home.service.mst', 'utf8').toString(), modulesActive));

 fs.writeFileSync('src/app/app-routing.module.ts', mustache.render(fs.readFileSync('deployment/app-routing.module.mst', 'utf8').toString(), modulesActive));

 fs.writeFileSync('src/app/core/components/base-navigation.component.ts', mustache.render(fs.readFileSync('deployment/base-navigation.component.mst', 'utf8').toString(), modulesActive));

+fs.writeFileSync('src/app/app-overview/apps.ts', fs.readFileSync('deployment/apps.ts'));

 fs.writeFileSync('src/scss/sp/sp-theme.scss', fs.readFileSync('deployment/sp-theme.scss'));

 fs.writeFileSync('src/app/services/app.constants.ts', fs.readFileSync('deployment/app-constants.ts', 'utf8'));

 

diff --git a/ui/deployment/sp-theme.scss b/ui/deployment/sp-theme.scss
index db812e6..286bd61 100644
--- a/ui/deployment/sp-theme.scss
+++ b/ui/deployment/sp-theme.scss
@@ -163,7 +163,10 @@
 .small .mat-tab-label-content {
   text-transform: none;
   font-size: 11pt;
+}
 
+:root {
+  --color-loading-bar: #{mat-color($accent)};
 }
 
 .dark-mode {
@@ -174,6 +177,19 @@
     background: #121212;
   }
 
+  .mat-button-toggle-checked {
+    background: var(--color-accent);
+    color: var(--color-bg-0);
+  }
+
+  .mat-button-toggle-checked.mat-button-toggle-appearance-standard {
+    color: var(--color-bg-0);
+  }
+
+  .mat-button-toggle-appearance-standard .mat-button-toggle-label-content {
+    line-height: 30px;
+  }
+
   .mat-toolbar.mat-primary {
     color: #121212;
   }
@@ -219,6 +235,19 @@
     background: #FFFFFF;
   }
 
+  .mat-button-toggle-checked {
+    background: var(--color-accent);
+    color: var(--color-bg-0);
+  }
+
+  .mat-button-toggle-checked.mat-button-toggle-appearance-standard {
+    color: var(--color-bg-0);
+  }
+
+  .mat-button-toggle-appearance-standard .mat-button-toggle-label-content {
+    line-height: 30px;
+  }
+
 
   --color-primary: #{mat-color($primary)};
   --color-accent: #{mat-color($accent)};
diff --git a/ui/package.json b/ui/package.json
index e4eb153..60b734d 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -8,17 +8,17 @@
     "url": "https://github.com/apache/incubator-streampipes"
   },
   "scripts": {
-    "build-libs": "ng build @streampipes/shared-ui && ng build @streampipes/platform-services",
-    "install-libs": "npm install @streampipes/shared-ui@file:./dist/streampipes/shared-ui @streampipes/platform-services@file:./dist/streampipes/platform-services --no-save",
+    "build-libs": "ng build @streampipes/platform-services && ng build @streampipes/shared-ui",
+    "install-libs": "npm install @streampipes/platform-services@file:./dist/streampipes/platform-services @streampipes/shared-ui@file:./dist/streampipes/shared-ui --no-save",
     "build-libraries": "npm run build-libs && npm run install-libs",
     "start": "node ./deployment/prebuild.js && npm run build-libraries && ng serve",
     "test": "node ./deployment/prebuild.js && npm run build-libraries && ng test",
     "start-plain": "npm run build-libraries && ng serve",
-    "build-plain": "set NODE_OPTIONS=--max-old-space-size=10192 && npm run build-libraries && ng build --configuration production",
+    "build-plain": "set NODE_OPTIONS=--max-old-space-size=8192 && npm run build-libraries && ng build --configuration production",
     "run-prebuild-script": "node ./deployment/prebuild.js",
-    "build": "node ./deployment/prebuild.js && set NODE_OPTIONS=--max-old-space-size=10192 && npm run build-libraries && ng build --configuration production",
-    "build-dev": "node ./deployment/prebuild.js && set NODE_OPTIONS=--max-old-space-size=10192 && npm run build-libraries && ng build",
-    "build-rc": "node ./deployment/prebuild.js rel && set NODE_OPTIONS=--max-old-space-size=10192 && npm run build-libraries && ng build --configuration production",
+    "build": "node ./deployment/prebuild.js && set NODE_OPTIONS=--max-old-space-size=8192 && npm run build-libraries && ng build --configuration production",
+    "build-dev": "node ./deployment/prebuild.js && set NODE_OPTIONS=--max-old-space-size=8192 && npm run build-libraries && ng build",
+    "build-rc": "node ./deployment/prebuild.js rel && set NODE_OPTIONS=--max-old-space-size=8192 && npm run build-libraries && ng build --configuration production",
     "lint": "tslint -c tslint.json 'src/**/*.ts*",
     "analyze": "webpack-bundle-analyzer dist/stats.json",
     "test-cypress-open": "cypress open",
@@ -43,7 +43,7 @@
     "@angular/platform-browser-dynamic": "^13.3.0",
     "@angular/router": "^13.3.0",
     "@asymmetrik/ngx-leaflet": "6.0.1",
-    "@auth0/angular-jwt": "^5.0.2",
+    "@auth0/angular-jwt": "5.0.2",
     "@circlon/angular-tree-component": "^11.0.4",
     "@ctrl/ngx-codemirror": "5.1.1",
     "@danielmoncada/angular-datetime-picker": "^13.1.1",
@@ -58,7 +58,7 @@
     "@panzoom/panzoom": "^4.4.3",
     "@swimlane/ngx-charts": "16.0.0",
     "angular-datatables": "^13.0.1",
-    "angular-gridster2": "^13.1.1",
+    "angular-gridster2": "13.1.1",
     "angular-plotly.js": "^4.0.0",
     "angular2-uuid": "1.1.1",
     "codemirror": "^5.55.0",
@@ -75,7 +75,7 @@
     "konva": "3.2.4",
     "leaflet": "1.6.0",
     "lodash": "4.17.21",
-    "material-icons": "^0.5.3",
+    "material-icons": "^1.11.4",
     "ngx-color-picker": "^11.0.0",
     "ngx-echarts": "^8.0.1",
     "ngx-quill": "15.0.0",
@@ -87,7 +87,7 @@
     "shepherd.js": "^9.0.0",
     "showdown": "1.9.1",
     "stream-browserify": "3.0.0",
-    "swagger-ui": "^4.2.1",
+    "swagger-ui": "4.12.0",
     "tslib": "^2.0.0",
     "zone.js": "~0.11.4"
   },
@@ -96,8 +96,8 @@
     "@angular-devkit/build-angular": "^13.3.0",
     "@angular/cli": "^13.3.0",
     "@angular/compiler-cli": "^13.3.0",
-    "@cypress/webpack-batteries-included-preprocessor": "^2.0.0",
-    "@cypress/webpack-preprocessor": "^5.11.1",
+    "@cypress/webpack-batteries-included-preprocessor": "2.2.3",
+    "@cypress/webpack-preprocessor": "5.12.0",
     "@ngtools/webpack": "^13.3.0",
     "@types/angular": "^1.7.4",
     "@types/jasmine": "~3.6.0",
@@ -107,6 +107,7 @@
     "@types/node": "^12.19.3",
     "@types/rx": "^4.1.2",
     "@types/showdown": "1.9.3",
+    "ajv-keywords": "^5.1.0",
     "assert": "^2.0.0",
     "codelyzer": "^6.0.0",
     "compression-webpack-plugin": "^9.2.0",
@@ -114,7 +115,6 @@
     "csv-string": "^4.1.0",
     "cypress": "^9.5.2",
     "cypress-file-upload": "^5.0.8",
-    "file-loader": "^5.1.0",
     "html-webpack-plugin": "^5.5.0",
     "jasmine-core": "^3.6.0",
     "js-yaml": "^3.14.0",
@@ -131,14 +131,17 @@
     "prettier": "1.14.2",
     "raw-loader": "^4.0.2",
     "resize-observer-polyfill": "^1.5.1",
-    "sass-loader": "^12.4.0",
-    "style-loader": "^0.23.1",
     "to-string-loader": "^1.1.5",
     "tslint": "~6.1.0",
     "tslint-config-prettier": "^1.15.0",
     "typescript": "4.6.2",
-    "webpack": "^5.72.0",
-    "webpack-cli": "^4.9.0",
+    "webpack": "^5.73.0",
+    "webpack-cli": "^4.9.2",
     "webpack-merge": "^5.8.0"
+  },
+  "overrides": {
+    "@angular-architects/module-federation": {
+      "@angular-architects/module-federation-runtime": "14.0.1"
+    }
   }
 }
diff --git a/ui/src/app/connect/services/data-marketplace.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
similarity index 67%
rename from ui/src/app/connect/services/data-marketplace.service.ts
rename to ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
index a8dc5f9..f337ab4 100644
--- a/ui/src/app/connect/services/data-marketplace.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
@@ -19,25 +19,16 @@
 import { Injectable } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
 import { map } from 'rxjs/operators';
-import { ConnectService } from './connect.service';
-import {
-  AdapterDescription,
-  AdapterDescriptionUnion,
-  GenericAdapterSetDescription,
-  GenericAdapterStreamDescription,
-  Message,
-  SpecificAdapterSetDescription,
-  SpecificAdapterStreamDescription,
-  PlatformServicesCommons
-} from '@streampipes/platform-services';
-import { Observable } from 'rxjs';
 
-@Injectable()
-export class DataMarketplaceService {
+import { Observable } from 'rxjs';
+import { PlatformServicesCommons } from './commons.service';
+import { AdapterDescription, AdapterDescriptionUnion, Message } from '../model/gen/streampipes-model';
+
+@Injectable({providedIn: 'root'})
+export class AdapterService {
 
   constructor(
       private http: HttpClient,
-      private connectService: ConnectService,
       private platformServicesCommons: PlatformServicesCommons) {
   }
 
@@ -47,13 +38,16 @@
 
   getAdapterDescriptions(): Observable<AdapterDescriptionUnion[]> {
     return this.requestAdapterDescriptions('/master/description/adapters');
-
   }
 
   getAdapters(): Observable<AdapterDescriptionUnion[]> {
     return this.requestAdapterDescriptions('/master/adapters');
   }
 
+  deleteAdapterDescription(adapterId: string): Observable<any> {
+    return this.http.delete(`${this.connectPath}/master/description/${adapterId}`);
+  }
+
   requestAdapterDescriptions(path: string): Observable<AdapterDescriptionUnion[]> {
     return this.http
       .get(
@@ -100,26 +94,6 @@
     );
   }
 
-  cloneAdapterDescription(toClone: AdapterDescriptionUnion): AdapterDescriptionUnion {
-    let result: AdapterDescriptionUnion;
-
-    if (this.connectService.isGenericDescription(toClone)) {
-      if (toClone instanceof GenericAdapterStreamDescription) {
-        result = GenericAdapterStreamDescription.fromData(toClone, new GenericAdapterStreamDescription());
-      } else if (toClone instanceof GenericAdapterSetDescription) {
-        result = GenericAdapterSetDescription.fromData(toClone, new GenericAdapterSetDescription());
-      }
-    } else {
-      if (toClone instanceof SpecificAdapterStreamDescription) {
-        result = SpecificAdapterStreamDescription.fromData(toClone, new SpecificAdapterStreamDescription());
-      } else if (toClone instanceof SpecificAdapterSetDescription) {
-        result = SpecificAdapterSetDescription.fromData(toClone, new SpecificAdapterSetDescription());
-      }
-    }
-
-    return result;
-  }
-
   getAssetUrl(appId) {
     return `${this.connectPath}/master/description/${appId}/assets`;
   }
diff --git a/ui/projects/streampipes/platform-services/src/lib/apis/asset-management.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/asset-management.service.ts
new file mode 100644
index 0000000..5cf4ce2
--- /dev/null
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/asset-management.service.ts
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { PlatformServicesCommons } from './commons.service';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class AssetManagementService {
+
+  constructor(private http: HttpClient,
+              private platformServicesCommons: PlatformServicesCommons) {
+  }
+
+  createAsset(asset: any): Observable<any> {
+    return this.http.post(this.assetBasePath, asset);
+  }
+
+  getAllAssets(): Observable<any> {
+    return this.http.get(this.assetBasePath);
+  }
+
+  getAsset(assetId: string): Observable<any> {
+    return this.http.get(`${this.assetBasePath}/${assetId}`);
+  }
+
+  updateAsset(asset: any): Observable<any> {
+    return this.http.put(`${this.assetBasePath}/${asset._id}`, asset);
+  }
+
+  deleteAsset(assetId: string, rev: string): Observable<any> {
+    return this.http.delete(`${this.assetBasePath}/${assetId}/${rev}`);
+  }
+
+  private get assetBasePath() {
+    return this.platformServicesCommons.apiBasePath + '/assets';
+  }
+
+}
diff --git a/ui/src/app/dashboard/services/dashboard.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/dashboard.service.ts
similarity index 92%
rename from ui/src/app/dashboard/services/dashboard.service.ts
rename to ui/projects/streampipes/platform-services/src/lib/apis/dashboard.service.ts
index bcb6940..e06d548 100644
--- a/ui/src/app/dashboard/services/dashboard.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/dashboard.service.ts
@@ -20,16 +20,15 @@
 import { Injectable } from '@angular/core';
 import { map } from 'rxjs/operators';
 import { Observable } from 'rxjs';
-import { MeasurementUnit } from '../../core-model/measurement-unit/MeasurementUnit';
-import {
-  Dashboard,
-  DashboardWidgetModel,
-  Pipeline,
-  VisualizablePipeline,
-  PlatformServicesCommons
-} from '@streampipes/platform-services';
+import { MeasurementUnit } from '../model/measurement-unit/MeasurementUnit';
+import { PlatformServicesCommons } from './commons.service';
+import { DashboardWidgetModel, Pipeline, VisualizablePipeline } from '../model/gen/streampipes-model';
+import { Dashboard } from '../model/dashboard/dashboard.model';
 
-@Injectable()
+
+@Injectable({
+  providedIn: 'root'
+})
 export class DashboardService {
 
 
diff --git a/ui/projects/streampipes/platform-services/src/lib/apis/data-view-data-explorer.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/data-view-data-explorer.service.ts
index ea89b7d..3c721f0 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/data-view-data-explorer.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/data-view-data-explorer.service.ts
@@ -46,6 +46,12 @@
     return this.sharedDatalakeRestService.getDashboards(this.dashboardUrl);
   }
 
+  getDataView(dataViewId: string): Observable<Dashboard> {
+    return this.http.get(this.dashboardUrl + '/' + dataViewId).pipe(map(data => {
+      return data as Dashboard;
+    }));
+  }
+
   updateDashboard(dashboard: Dashboard): Observable<Dashboard> {
     return this.sharedDatalakeRestService.updateDashboard(this.dashboardUrl, dashboard);
   }
diff --git a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
index 249c9f5..6f78699 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
@@ -17,8 +17,8 @@
  */
 
 import { Injectable } from '@angular/core';
-import { HttpClient, HttpRequest } from '@angular/common/http';
-import { Observable } from 'rxjs';
+import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http';
+import { Observable, of } from 'rxjs';
 import { DataLakeMeasure, PageResult, SpQueryResult } from '../model/gen/streampipes-model';
 import { map } from 'rxjs/operators';
 import { DatalakeQueryParameters } from '../model/datalake/DatalakeQueryParameters';
@@ -38,6 +38,10 @@
     return this.baseUrl + '/api/v4' + '/datalake';
   }
 
+  public get dataLakeMeasureUrl() {
+    return this.baseUrl + '/api/v4/datalake/measure';
+  }
+
   getAllMeasurementSeries(): Observable<DataLakeMeasure[]> {
     const url = this.dataLakeUrl + '/measurements/';
     return this.http.get(url).pipe(map(response => {
@@ -45,13 +49,30 @@
     }));
   }
 
+  getMeasurement(id: string): Observable<DataLakeMeasure> {
+    return this.http.get(`${this.dataLakeMeasureUrl}/${id}`).pipe(map(res => res as DataLakeMeasure));
+  }
+
+  performMultiQuery(queryParams: DatalakeQueryParameters[]): Observable<SpQueryResult[]> {
+    return this.http.post(`${this.dataLakeUrl}/query`, queryParams, {headers: {ignoreLoadingBar: ''}})
+      .pipe(map(response => response as SpQueryResult[]));
+  }
+
   getData(index: string,
           queryParams: DatalakeQueryParameters,
           ignoreLoadingBar?: boolean): Observable<SpQueryResult> {
-    const url = this.dataLakeUrl + '/measurements/' + index;
-    const headers = ignoreLoadingBar ? { ignoreLoadingBar: '' } : {};
-    // @ts-ignore
-    return this.http.get<SpQueryResult>(url, { params: queryParams }, headers);
+
+    const columns = queryParams.columns;
+    if (columns === '') {
+      const emptyQueryResult = new SpQueryResult();
+      emptyQueryResult.total = 0;
+      return of(emptyQueryResult);
+    } else {
+      const url = this.dataLakeUrl + '/measurements/' + index;
+      const headers = ignoreLoadingBar ? {ignoreLoadingBar: ''} : {};
+      // @ts-ignore
+      return this.http.get<SpQueryResult>(url, {params: queryParams, headers});
+    }
   }
 
 
@@ -62,77 +83,61 @@
       itemsPerPage, undefined, undefined, order, undefined, undefined);
 
     // @ts-ignore
-    return this.http.get<PageResult>(url, { params: queryParams });
+    return this.http.get<PageResult>(url, {params: queryParams});
   }
 
   getTagValues(index: string,
                fieldNames: string[]): Observable<Map<string, string[]>> {
-    return this.http.get(this.dataLakeUrl + '/measurements/' + index + '/tags?fields=' + fieldNames.toString())
-      .pipe(map(r => r as Map<string, string[]>));
+
+    if (fieldNames.length === 0) {
+      return of(new Map<string, string[]>());
+    } else {
+      return this.http.get(this.dataLakeUrl + '/measurements/' + index + '/tags?fields=' + fieldNames.toString())
+        .pipe(map(r => r as Map<string, string[]>));
+
+    }
   }
 
-  // getGroupedData(index: string, groupingTags: string, aggregationFunction?: string, columns?: string, startDate?: number, endDate?:
-  //   number, aggregationTimeUnit?: string, aggregationTimeValue?: number, order?: string, limit?: number):
-  //   Observable<SpQueryResult> {
-  //
-  //   const url = this.dataLakeUrl + '/measurements/' + index;
-  //   let _aggregationFunction = 'mean';
-  //   let timeInterval = '2000ms';
-  //
-  //   if (aggregationFunction) {
-  //     _aggregationFunction = aggregationFunction;
-  //   }
-  //
-  //   if (aggregationTimeUnit && aggregationTimeValue) {
-  //     timeInterval = aggregationTimeValue + aggregationTimeUnit;
-  //   }
-  //
-  //   const queryParams: DatalakeQueryParameters = this.getQueryParameters(columns, startDate, endDate, undefined, limit,
-  //     undefined, groupingTags, order, _aggregationFunction, timeInterval);
-  //
-  //   // @ts-ignore
-  //   return this.http.get<GroupedDataResult>(url, { params: queryParams });
-  // }
-
-  downloadRawData(index, format) {
-    const url = this.dataLakeUrl + '/measurements/' + index + '/download?format=' + format;
-
-    const request = new HttpRequest('GET', url, {
-      reportProgress: true,
-      responseType: 'text'
-    });
-
-    return this.http.request(request);
+  downloadRawData(index: string,
+                  format: string,
+                  delimiter: string,
+                  startTime?: number,
+                  endTime?: number) {
+    const queryParams = (startTime && endTime) ? {format, delimiter, startDate: startTime, endDate: endTime} : {
+      format,
+      delimiter
+    };
+    return this.buildDownloadRequest(index, queryParams);
   }
 
   downloadQueriedData(
-    index,
-    format,
-    startDate?,
-    endDate?,
-    columns?,
-    aggregationFunction?,
-    aggregationTimeUnit?,
-    aggregationTimeValue?,
-    groupingsTags?,
-    order?,
-    limit?,
-    offset?) {
-    const url = this.dataLakeUrl + '/measurements/' + index + '/download?format=' + format;
-    const timeInterval = aggregationTimeValue + aggregationTimeUnit;
+    index: string,
+    format: string,
+    delimiter: string,
+    queryParams: DatalakeQueryParameters) {
 
-    const queryParams: DatalakeQueryParameters = this.getQueryParameters(columns, startDate, endDate, undefined,
-      limit, offset, groupingsTags, order, aggregationFunction, timeInterval);
+    (queryParams as any).format = format;
+    (queryParams as any).delimiter = delimiter;
+    return this.buildDownloadRequest(index, queryParams);
 
+  }
+
+  buildDownloadRequest(index: string,
+                       queryParams: any) {
+    const url = this.dataLakeUrl + '/measurements/' + index + '/download';
     const request = new HttpRequest('GET', url, {
       reportProgress: true,
       responseType: 'text',
-      params: queryParams
+      params: this.toHttpParams(queryParams)
     });
 
     return this.http.request(request);
   }
 
+  toHttpParams(queryParamObject: any): HttpParams {
+    return new HttpParams({fromObject: queryParamObject});
+  }
+
   removeData(index: string) {
     const url = this.dataLakeUrl + '/measurements/' + index;
 
diff --git a/ui/projects/streampipes/platform-services/src/lib/apis/generic-storage.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/generic-storage.service.ts
new file mode 100644
index 0000000..4cdc45d
--- /dev/null
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/generic-storage.service.ts
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { PlatformServicesCommons } from './commons.service';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class GenericStorageService {
+
+  constructor(private http: HttpClient,
+              private platformServicesCommons: PlatformServicesCommons) {
+  }
+
+  createDocument(appDocName: string,
+                 document: any): Observable<any> {
+    return this.http.post(this.getAppDocPath(appDocName), document);
+  }
+
+  getAllDocuments(appDocName: string): Observable<any> {
+    return this.http.get(this.getAppDocPath(appDocName));
+  }
+
+  getDocument(appDocName: string,
+              documentId: string): Observable<any> {
+    return this.http.get(`${this.getAppDocPath(appDocName)}/${documentId}`);
+  }
+
+  updateDocument(appDocName: string,
+                 document: any): Observable<any> {
+    return this.http.put(`${this.getAppDocPath(appDocName)}/${document._id}`, document);
+  }
+
+  deleteDocument(appDocName: string,
+                 documentId: string,
+                 rev: string): Observable<any> {
+    return this.http.delete(`${this.getAppDocPath(appDocName)}/${documentId}/${rev}`);
+  }
+
+  private getAppDocPath(appDocName: string): string {
+    return this.genericStorageBasePath + '/' + appDocName;
+  }
+
+  private get genericStorageBasePath() {
+    return this.platformServicesCommons.apiBasePath + '/storage-generic';
+  }
+
+}
diff --git a/ui/projects/streampipes/platform-services/src/lib/apis/pipeline-element-template.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/pipeline-element-template.service.ts
index 4bfef5c..6cca1d5 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/pipeline-element-template.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/pipeline-element-template.service.ts
@@ -20,6 +20,8 @@
 import { HttpClient } from '@angular/common/http';
 import { Observable } from 'rxjs';
 import {
+  AdapterDescription,
+  AdapterDescriptionUnion,
   DataProcessorInvocation,
   DataSinkInvocation,
   PipelineElementTemplate
@@ -46,6 +48,10 @@
         }));
   }
 
+  deletePipelineElementTemplate(templateId: string): Observable<any> {
+    return this.http.delete(`${this.platformServicesCommons.apiBasePath}/pipeline-element-templates/${templateId}`);
+  }
+
   getConfiguredDataProcessorForTemplate(templateId: string, invocation: DataProcessorInvocation): Observable<DataProcessorInvocation> {
     return this.http.post(this.platformServicesCommons.apiBasePath
         + '/pipeline-element-templates/' + templateId + '/processor', invocation)
@@ -62,6 +68,12 @@
         }));
   }
 
+  getConfiguredAdapterForTemplate(templateId: string,
+                                  adapter: AdapterDescriptionUnion): Observable<any> {
+    return this.http.post(this.platformServicesCommons.apiBasePath
+      + '/pipeline-element-templates/' + templateId + '/adapter', adapter);
+  }
+
   storePipelineElementTemplate(template: PipelineElementTemplate) {
     return this.http.post(this.platformServicesCommons.apiBasePath + '/pipeline-element-templates', template);
   }
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts b/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
new file mode 100644
index 0000000..626e627
--- /dev/null
+++ b/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+export interface AssetLinkType {
+  linkType: string;
+  linkLabel: string;
+  linkColor: string;
+  linkIcon?: string;
+  linkQueryHint?: string;
+  navPaths: string[];
+  navigationActive: boolean;
+}
+
+export interface AssetType {
+  assetIcon: string;
+  assetIconColor: string;
+  assetTypeCategory: string;
+  assetTypeLabel: string;
+}
+
+export interface AssetLink {
+  resourceId: string;
+  linkType: 'data-view' | 'dashboard' | 'adapter' | 'source' | string;
+  linkLabel: string;
+  queryHint: string;
+  editingDisabled: boolean;
+  navigationActive: boolean;
+}
+
+export interface SpAsset {
+  assetId: string;
+  assetName: string;
+  assetDescription: string;
+
+  assetType: AssetType;
+  assetLinks: AssetLink[];
+
+  assets: SpAsset[];
+}
+
+export interface SpAssetModel extends SpAsset {
+  _id: string;
+  _rev: string;
+
+  appDocType: string;
+
+  removable: boolean;
+}
+
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/datalake/DatalakeQueryParameters.ts b/ui/projects/streampipes/platform-services/src/lib/model/datalake/DatalakeQueryParameters.ts
index 3cfd937..d694935 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/datalake/DatalakeQueryParameters.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/datalake/DatalakeQueryParameters.ts
@@ -32,5 +32,8 @@
   public filter: string;
   public maximumAmountOfEvents: number;
 
+  // should be only used for multi-query requests
+  public measureName: string;
+  public forId: string;
 }
 
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 393aa4c..b6e2425 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -15,13 +15,14 @@
  *   limitations under the License.
  */
 
+
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 2.27.744 on 2022-04-25 13:56:39.
+// Generated using typescript-generator version 2.27.744 on 2022-08-23 09:28:28.
 
 export class AbstractStreamPipesEntity {
-    "@class": "org.apache.streampipes.model.base.AbstractStreamPipesEntity" | "org.apache.streampipes.model.base.NamedStreamPipesEntity" | "org.apache.streampipes.model.connect.adapter.AdapterDescription" | "org.apache.streampipes.model.connect.adapter.AdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.AdapterStreamDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterStreamDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription" | "org.apache.streampipes.model.connect.grounding.ProtocolDescription" | "org.apache.streampipes.model.graph.DataSourceDescription" | "org.apache.streampipes.model.template.PipelineTemplateDescription" | "org.apache.streampipes.model.connect.grounding.FormatDescription" | "org.apache.streampipes.model.SpDataStream" | "org.apache.streampipes.model.SpDataSet" | "org.apache.streampipes.model.base.InvocableStreamPipesEntity" | "org.apache.streampipes.model.graph.DataProcessorInvocation" | "org.apache.streampipes.model.graph.DataSinkInvocation" | "org.apache.streampipes.model.base.UnnamedStreamPipesEntity" | "org.apache.streampipes.model.connect.guess.GuessSchema" | "org.apache.streampipes.model.connect.rules.TransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription" | "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.StreamTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.SchemaTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.CreateNestedRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription" | "org.apache.streampipes.model.dashboard.DashboardWidgetSettings" | "org.apache.streampipes.model.datalake.DataLakeMeasure" | "org.apache.streampipes.model.runtime.RuntimeOptionsRequest" | "org.apache.streampipes.model.runtime.RuntimeOptionsResponse" | "org.apache.streampipes.model.staticproperty.StaticProperty" | "org.apache.streampipes.model.staticproperty.CodeInputStaticProperty" | "org.apache.streampipes.model.staticproperty.CollectionStaticProperty" | "org.apache.streampipes.model.staticproperty.ColorPickerStaticProperty" | "org.apache.streampipes.model.staticproperty.DomainStaticProperty" | "org.apache.streampipes.model.staticproperty.FileStaticProperty" | "org.apache.streampipes.model.staticproperty.FreeTextStaticProperty" | "org.apache.streampipes.model.staticproperty.MatchingStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableTreeInputStaticProperty" | "org.apache.streampipes.model.staticproperty.SecretStaticProperty" | "org.apache.streampipes.model.staticproperty.StaticPropertyAlternative" | "org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives" | "org.apache.streampipes.model.staticproperty.StaticPropertyGroup" | "org.apache.streampipes.model.staticproperty.SlideToggleStaticProperty" | "org.apache.streampipes.model.staticproperty.SelectionStaticProperty" | "org.apache.streampipes.model.staticproperty.AnyStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty" | "org.apache.streampipes.model.staticproperty.OneOfStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty" | "org.apache.streampipes.model.staticproperty.MappingProperty" | "org.apache.streampipes.model.staticproperty.MappingPropertyUnary" | "org.apache.streampipes.model.staticproperty.MappingPropertyNary" | "org.apache.streampipes.model.template.PipelineTemplateInvocation" | "org.apache.streampipes.model.ApplicationLink" | "org.apache.streampipes.model.grounding.EventGrounding" | "org.apache.streampipes.model.schema.EventSchema" | "org.apache.streampipes.model.template.BoundPipelineElement" | "org.apache.streampipes.model.grounding.TransportProtocol" | "org.apache.streampipes.model.grounding.JmsTransportProtocol" | "org.apache.streampipes.model.grounding.KafkaTransportProtocol" | "org.apache.streampipes.model.grounding.MqttTransportProtocol" | "org.apache.streampipes.model.grounding.TransportFormat" | "org.apache.streampipes.model.quality.EventStreamQualityRequirement" | "org.apache.streampipes.model.quality.MeasurementCapability" | "org.apache.streampipes.model.quality.MeasurementObject" | "org.apache.streampipes.model.schema.EventProperty" | "org.apache.streampipes.model.schema.EventPropertyList" | "org.apache.streampipes.model.schema.EventPropertyNested" | "org.apache.streampipes.model.schema.EventPropertyPrimitive" | "org.apache.streampipes.model.output.OutputStrategy" | "org.apache.streampipes.model.output.AppendOutputStrategy" | "org.apache.streampipes.model.output.CustomOutputStrategy" | "org.apache.streampipes.model.output.CustomTransformOutputStrategy" | "org.apache.streampipes.model.output.FixedOutputStrategy" | "org.apache.streampipes.model.output.KeepOutputStrategy" | "org.apache.streampipes.model.output.ListOutputStrategy" | "org.apache.streampipes.model.output.TransformOutputStrategy" | "org.apache.streampipes.model.output.UserDefinedOutputStrategy" | "org.apache.streampipes.model.monitoring.ElementStatusInfoSettings" | "org.apache.streampipes.model.staticproperty.Option" | "org.apache.streampipes.model.staticproperty.SupportedProperty" | "org.apache.streampipes.model.staticproperty.PropertyValueSpecification" | "org.apache.streampipes.model.grounding.TopicDefinition" | "org.apache.streampipes.model.grounding.SimpleTopicDefinition" | "org.apache.streampipes.model.grounding.WildcardTopicDefinition" | "org.apache.streampipes.model.quality.MeasurementProperty" | "org.apache.streampipes.model.quality.EventStreamQualityDefinition" | "org.apache.streampipes.model.quality.Frequency" | "org.apache.streampipes.model.quality.Latency" | "org.apache.streampipes.model.quality.EventPropertyQualityDefinition" | "org.apache.streampipes.model.quality.Accuracy" | "org.apache.streampipes.model.quality.MeasurementRange" | "org.apache.streampipes.model.quality.Precision" | "org.apache.streampipes.model.quality.Resolution" | "org.apache.streampipes.model.quality.EventPropertyQualityRequirement" | "org.apache.streampipes.model.output.PropertyRenameRule" | "org.apache.streampipes.model.schema.ValueSpecification" | "org.apache.streampipes.model.schema.QuantitativeValue" | "org.apache.streampipes.model.schema.Enumeration" | "org.apache.streampipes.model.output.TransformOperation" | "org.apache.streampipes.model.grounding.WildcardTopicMapping";
+    "@class": "org.apache.streampipes.model.base.AbstractStreamPipesEntity" | "org.apache.streampipes.model.base.NamedStreamPipesEntity" | "org.apache.streampipes.model.connect.adapter.AdapterDescription" | "org.apache.streampipes.model.connect.adapter.AdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.AdapterStreamDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterStreamDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription" | "org.apache.streampipes.model.connect.grounding.ProtocolDescription" | "org.apache.streampipes.model.graph.DataSourceDescription" | "org.apache.streampipes.model.template.PipelineTemplateDescription" | "org.apache.streampipes.model.connect.grounding.FormatDescription" | "org.apache.streampipes.model.SpDataStream" | "org.apache.streampipes.model.SpDataSet" | "org.apache.streampipes.model.base.InvocableStreamPipesEntity" | "org.apache.streampipes.model.graph.DataProcessorInvocation" | "org.apache.streampipes.model.graph.DataSinkInvocation" | "org.apache.streampipes.model.base.UnnamedStreamPipesEntity" | "org.apache.streampipes.model.connect.guess.GuessSchema" | "org.apache.streampipes.model.connect.rules.TransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.StreamTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.SchemaTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.CreateNestedRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription" | "org.apache.streampipes.model.dashboard.DashboardWidgetSettings" | "org.apache.streampipes.model.datalake.DataLakeMeasure" | "org.apache.streampipes.model.runtime.RuntimeOptionsRequest" | "org.apache.streampipes.model.runtime.RuntimeOptionsResponse" | "org.apache.streampipes.model.staticproperty.StaticProperty" | "org.apache.streampipes.model.staticproperty.CodeInputStaticProperty" | "org.apache.streampipes.model.staticproperty.CollectionStaticProperty" | "org.apache.streampipes.model.staticproperty.ColorPickerStaticProperty" | "org.apache.streampipes.model.staticproperty.DomainStaticProperty" | "org.apache.streampipes.model.staticproperty.FileStaticProperty" | "org.apache.streampipes.model.staticproperty.FreeTextStaticProperty" | "org.apache.streampipes.model.staticproperty.MatchingStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableTreeInputStaticProperty" | "org.apache.streampipes.model.staticproperty.SecretStaticProperty" | "org.apache.streampipes.model.staticproperty.StaticPropertyAlternative" | "org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives" | "org.apache.streampipes.model.staticproperty.StaticPropertyGroup" | "org.apache.streampipes.model.staticproperty.SlideToggleStaticProperty" | "org.apache.streampipes.model.staticproperty.SelectionStaticProperty" | "org.apache.streampipes.model.staticproperty.AnyStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty" | "org.apache.streampipes.model.staticproperty.OneOfStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty" | "org.apache.streampipes.model.staticproperty.MappingProperty" | "org.apache.streampipes.model.staticproperty.MappingPropertyUnary" | "org.apache.streampipes.model.staticproperty.MappingPropertyNary" | "org.apache.streampipes.model.template.PipelineTemplateInvocation" | "org.apache.streampipes.model.ApplicationLink" | "org.apache.streampipes.model.grounding.EventGrounding" | "org.apache.streampipes.model.schema.EventSchema" | "org.apache.streampipes.model.template.BoundPipelineElement" | "org.apache.streampipes.model.grounding.TransportProtocol" | "org.apache.streampipes.model.grounding.JmsTransportProtocol" | "org.apache.streampipes.model.grounding.KafkaTransportProtocol" | "org.apache.streampipes.model.grounding.MqttTransportProtocol" | "org.apache.streampipes.model.grounding.TransportFormat" | "org.apache.streampipes.model.quality.EventStreamQualityRequirement" | "org.apache.streampipes.model.quality.MeasurementCapability" | "org.apache.streampipes.model.quality.MeasurementObject" | "org.apache.streampipes.model.schema.EventProperty" | "org.apache.streampipes.model.schema.EventPropertyList" | "org.apache.streampipes.model.schema.EventPropertyNested" | "org.apache.streampipes.model.schema.EventPropertyPrimitive" | "org.apache.streampipes.model.output.OutputStrategy" | "org.apache.streampipes.model.output.AppendOutputStrategy" | "org.apache.streampipes.model.output.CustomOutputStrategy" | "org.apache.streampipes.model.output.CustomTransformOutputStrategy" | "org.apache.streampipes.model.output.FixedOutputStrategy" | "org.apache.streampipes.model.output.KeepOutputStrategy" | "org.apache.streampipes.model.output.ListOutputStrategy" | "org.apache.streampipes.model.output.TransformOutputStrategy" | "org.apache.streampipes.model.output.UserDefinedOutputStrategy" | "org.apache.streampipes.model.monitoring.ElementStatusInfoSettings" | "org.apache.streampipes.model.staticproperty.Option" | "org.apache.streampipes.model.staticproperty.SupportedProperty" | "org.apache.streampipes.model.staticproperty.PropertyValueSpecification" | "org.apache.streampipes.model.grounding.TopicDefinition" | "org.apache.streampipes.model.grounding.SimpleTopicDefinition" | "org.apache.streampipes.model.grounding.WildcardTopicDefinition" | "org.apache.streampipes.model.quality.MeasurementProperty" | "org.apache.streampipes.model.quality.EventStreamQualityDefinition" | "org.apache.streampipes.model.quality.Frequency" | "org.apache.streampipes.model.quality.Latency" | "org.apache.streampipes.model.quality.EventPropertyQualityDefinition" | "org.apache.streampipes.model.quality.Accuracy" | "org.apache.streampipes.model.quality.MeasurementRange" | "org.apache.streampipes.model.quality.Precision" | "org.apache.streampipes.model.quality.Resolution" | "org.apache.streampipes.model.quality.EventPropertyQualityRequirement" | "org.apache.streampipes.model.output.PropertyRenameRule" | "org.apache.streampipes.model.schema.ValueSpecification" | "org.apache.streampipes.model.schema.QuantitativeValue" | "org.apache.streampipes.model.schema.Enumeration" | "org.apache.streampipes.model.output.TransformOperation" | "org.apache.streampipes.model.grounding.WildcardTopicMapping";
     elementId: string;
 
     static fromData(data: AbstractStreamPipesEntity, target?: AbstractStreamPipesEntity): AbstractStreamPipesEntity {
@@ -36,7 +37,7 @@
 }
 
 export class UnnamedStreamPipesEntity extends AbstractStreamPipesEntity {
-    "@class": "org.apache.streampipes.model.base.UnnamedStreamPipesEntity" | "org.apache.streampipes.model.connect.guess.GuessSchema" | "org.apache.streampipes.model.connect.rules.TransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription" | "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.StreamTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.SchemaTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.CreateNestedRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription" | "org.apache.streampipes.model.dashboard.DashboardWidgetSettings" | "org.apache.streampipes.model.datalake.DataLakeMeasure" | "org.apache.streampipes.model.runtime.RuntimeOptionsRequest" | "org.apache.streampipes.model.runtime.RuntimeOptionsResponse" | "org.apache.streampipes.model.staticproperty.StaticProperty" | "org.apache.streampipes.model.staticproperty.CodeInputStaticProperty" | "org.apache.streampipes.model.staticproperty.CollectionStaticProperty" | "org.apache.streampipes.model.staticproperty.ColorPickerStaticProperty" | "org.apache.streampipes.model.staticproperty.DomainStaticProperty" | "org.apache.streampipes.model.staticproperty.FileStaticProperty" | "org.apache.streampipes.model.staticproperty.FreeTextStaticProperty" | "org.apache.streampipes.model.staticproperty.MatchingStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableTreeInputStaticProperty" | "org.apache.streampipes.model.staticproperty.SecretStaticProperty" | "org.apache.streampipes.model.staticproperty.StaticPropertyAlternative" | "org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives" | "org.apache.streampipes.model.staticproperty.StaticPropertyGroup" | "org.apache.streampipes.model.staticproperty.SlideToggleStaticProperty" | "org.apache.streampipes.model.staticproperty.SelectionStaticProperty" | "org.apache.streampipes.model.staticproperty.AnyStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty" | "org.apache.streampipes.model.staticproperty.OneOfStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty" | "org.apache.streampipes.model.staticproperty.MappingProperty" | "org.apache.streampipes.model.staticproperty.MappingPropertyUnary" | "org.apache.streampipes.model.staticproperty.MappingPropertyNary" | "org.apache.streampipes.model.template.PipelineTemplateInvocation" | "org.apache.streampipes.model.ApplicationLink" | "org.apache.streampipes.model.grounding.EventGrounding" | "org.apache.streampipes.model.schema.EventSchema" | "org.apache.streampipes.model.template.BoundPipelineElement" | "org.apache.streampipes.model.grounding.TransportProtocol" | "org.apache.streampipes.model.grounding.JmsTransportProtocol" | "org.apache.streampipes.model.grounding.KafkaTransportProtocol" | "org.apache.streampipes.model.grounding.MqttTransportProtocol" | "org.apache.streampipes.model.grounding.TransportFormat" | "org.apache.streampipes.model.quality.EventStreamQualityRequirement" | "org.apache.streampipes.model.quality.MeasurementCapability" | "org.apache.streampipes.model.quality.MeasurementObject" | "org.apache.streampipes.model.schema.EventProperty" | "org.apache.streampipes.model.schema.EventPropertyList" | "org.apache.streampipes.model.schema.EventPropertyNested" | "org.apache.streampipes.model.schema.EventPropertyPrimitive" | "org.apache.streampipes.model.output.OutputStrategy" | "org.apache.streampipes.model.output.AppendOutputStrategy" | "org.apache.streampipes.model.output.CustomOutputStrategy" | "org.apache.streampipes.model.output.CustomTransformOutputStrategy" | "org.apache.streampipes.model.output.FixedOutputStrategy" | "org.apache.streampipes.model.output.KeepOutputStrategy" | "org.apache.streampipes.model.output.ListOutputStrategy" | "org.apache.streampipes.model.output.TransformOutputStrategy" | "org.apache.streampipes.model.output.UserDefinedOutputStrategy" | "org.apache.streampipes.model.monitoring.ElementStatusInfoSettings" | "org.apache.streampipes.model.staticproperty.Option" | "org.apache.streampipes.model.staticproperty.SupportedProperty" | "org.apache.streampipes.model.staticproperty.PropertyValueSpecification" | "org.apache.streampipes.model.grounding.TopicDefinition" | "org.apache.streampipes.model.grounding.SimpleTopicDefinition" | "org.apache.streampipes.model.grounding.WildcardTopicDefinition" | "org.apache.streampipes.model.quality.MeasurementProperty" | "org.apache.streampipes.model.quality.EventStreamQualityDefinition" | "org.apache.streampipes.model.quality.Frequency" | "org.apache.streampipes.model.quality.Latency" | "org.apache.streampipes.model.quality.EventPropertyQualityDefinition" | "org.apache.streampipes.model.quality.Accuracy" | "org.apache.streampipes.model.quality.MeasurementRange" | "org.apache.streampipes.model.quality.Precision" | "org.apache.streampipes.model.quality.Resolution" | "org.apache.streampipes.model.quality.EventPropertyQualityRequirement" | "org.apache.streampipes.model.output.PropertyRenameRule" | "org.apache.streampipes.model.schema.ValueSpecification" | "org.apache.streampipes.model.schema.QuantitativeValue" | "org.apache.streampipes.model.schema.Enumeration" | "org.apache.streampipes.model.output.TransformOperation" | "org.apache.streampipes.model.grounding.WildcardTopicMapping";
+    "@class": "org.apache.streampipes.model.base.UnnamedStreamPipesEntity" | "org.apache.streampipes.model.connect.guess.GuessSchema" | "org.apache.streampipes.model.connect.rules.TransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.StreamTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.SchemaTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.CreateNestedRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription" | "org.apache.streampipes.model.dashboard.DashboardWidgetSettings" | "org.apache.streampipes.model.datalake.DataLakeMeasure" | "org.apache.streampipes.model.runtime.RuntimeOptionsRequest" | "org.apache.streampipes.model.runtime.RuntimeOptionsResponse" | "org.apache.streampipes.model.staticproperty.StaticProperty" | "org.apache.streampipes.model.staticproperty.CodeInputStaticProperty" | "org.apache.streampipes.model.staticproperty.CollectionStaticProperty" | "org.apache.streampipes.model.staticproperty.ColorPickerStaticProperty" | "org.apache.streampipes.model.staticproperty.DomainStaticProperty" | "org.apache.streampipes.model.staticproperty.FileStaticProperty" | "org.apache.streampipes.model.staticproperty.FreeTextStaticProperty" | "org.apache.streampipes.model.staticproperty.MatchingStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableTreeInputStaticProperty" | "org.apache.streampipes.model.staticproperty.SecretStaticProperty" | "org.apache.streampipes.model.staticproperty.StaticPropertyAlternative" | "org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives" | "org.apache.streampipes.model.staticproperty.StaticPropertyGroup" | "org.apache.streampipes.model.staticproperty.SlideToggleStaticProperty" | "org.apache.streampipes.model.staticproperty.SelectionStaticProperty" | "org.apache.streampipes.model.staticproperty.AnyStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty" | "org.apache.streampipes.model.staticproperty.OneOfStaticProperty" | "org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty" | "org.apache.streampipes.model.staticproperty.MappingProperty" | "org.apache.streampipes.model.staticproperty.MappingPropertyUnary" | "org.apache.streampipes.model.staticproperty.MappingPropertyNary" | "org.apache.streampipes.model.template.PipelineTemplateInvocation" | "org.apache.streampipes.model.ApplicationLink" | "org.apache.streampipes.model.grounding.EventGrounding" | "org.apache.streampipes.model.schema.EventSchema" | "org.apache.streampipes.model.template.BoundPipelineElement" | "org.apache.streampipes.model.grounding.TransportProtocol" | "org.apache.streampipes.model.grounding.JmsTransportProtocol" | "org.apache.streampipes.model.grounding.KafkaTransportProtocol" | "org.apache.streampipes.model.grounding.MqttTransportProtocol" | "org.apache.streampipes.model.grounding.TransportFormat" | "org.apache.streampipes.model.quality.EventStreamQualityRequirement" | "org.apache.streampipes.model.quality.MeasurementCapability" | "org.apache.streampipes.model.quality.MeasurementObject" | "org.apache.streampipes.model.schema.EventProperty" | "org.apache.streampipes.model.schema.EventPropertyList" | "org.apache.streampipes.model.schema.EventPropertyNested" | "org.apache.streampipes.model.schema.EventPropertyPrimitive" | "org.apache.streampipes.model.output.OutputStrategy" | "org.apache.streampipes.model.output.AppendOutputStrategy" | "org.apache.streampipes.model.output.CustomOutputStrategy" | "org.apache.streampipes.model.output.CustomTransformOutputStrategy" | "org.apache.streampipes.model.output.FixedOutputStrategy" | "org.apache.streampipes.model.output.KeepOutputStrategy" | "org.apache.streampipes.model.output.ListOutputStrategy" | "org.apache.streampipes.model.output.TransformOutputStrategy" | "org.apache.streampipes.model.output.UserDefinedOutputStrategy" | "org.apache.streampipes.model.monitoring.ElementStatusInfoSettings" | "org.apache.streampipes.model.staticproperty.Option" | "org.apache.streampipes.model.staticproperty.SupportedProperty" | "org.apache.streampipes.model.staticproperty.PropertyValueSpecification" | "org.apache.streampipes.model.grounding.TopicDefinition" | "org.apache.streampipes.model.grounding.SimpleTopicDefinition" | "org.apache.streampipes.model.grounding.WildcardTopicDefinition" | "org.apache.streampipes.model.quality.MeasurementProperty" | "org.apache.streampipes.model.quality.EventStreamQualityDefinition" | "org.apache.streampipes.model.quality.Frequency" | "org.apache.streampipes.model.quality.Latency" | "org.apache.streampipes.model.quality.EventPropertyQualityDefinition" | "org.apache.streampipes.model.quality.Accuracy" | "org.apache.streampipes.model.quality.MeasurementRange" | "org.apache.streampipes.model.quality.Precision" | "org.apache.streampipes.model.quality.Resolution" | "org.apache.streampipes.model.quality.EventPropertyQualityRequirement" | "org.apache.streampipes.model.output.PropertyRenameRule" | "org.apache.streampipes.model.schema.ValueSpecification" | "org.apache.streampipes.model.schema.QuantitativeValue" | "org.apache.streampipes.model.schema.Enumeration" | "org.apache.streampipes.model.output.TransformOperation" | "org.apache.streampipes.model.grounding.WildcardTopicMapping";
 
     static fromData(data: UnnamedStreamPipesEntity, target?: UnnamedStreamPipesEntity): UnnamedStreamPipesEntity {
         if (!data) {
@@ -169,11 +170,11 @@
     eventGrounding: EventGrounding;
     icon: string;
     rules: TransformationRuleDescriptionUnion[];
-    schemaRules: any[];
+    schemaRules: TransformationRuleDescriptionUnion[];
     selectedEndpointUrl: string;
-    streamRules: any[];
+    streamRules: TransformationRuleDescriptionUnion[];
     userName: string;
-    valueRules: any[];
+    valueRules: TransformationRuleDescriptionUnion[];
 
     static fromData(data: AdapterDescription, target?: AdapterDescription): AdapterDescription {
         if (!data) {
@@ -192,9 +193,9 @@
         instance.selectedEndpointUrl = data.selectedEndpointUrl;
         instance.correspondingServiceGroup = data.correspondingServiceGroup;
         instance.correspondingDataStreamElementId = data.correspondingDataStreamElementId;
-        instance.valueRules = __getCopyArrayFn(__identity<any>())(data.valueRules);
-        instance.streamRules = __getCopyArrayFn(__identity<any>())(data.streamRules);
-        instance.schemaRules = __getCopyArrayFn(__identity<any>())(data.schemaRules);
+        instance.valueRules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.valueRules);
+        instance.streamRules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.streamRules);
+        instance.schemaRules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.schemaRules);
         return instance;
     }
 
@@ -215,6 +216,21 @@
     }
 }
 
+export class AdapterEventPreview {
+    inputData: { [index: string]: GuessTypeInfo };
+    rules: TransformationRuleDescriptionUnion[];
+
+    static fromData(data: AdapterEventPreview, target?: AdapterEventPreview): AdapterEventPreview {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new AdapterEventPreview();
+        instance.rules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.rules);
+        instance.inputData = __getCopyObjectFn(GuessTypeInfo.fromData)(data.inputData);
+        return instance;
+    }
+}
+
 export class AdapterSetDescription extends AdapterDescription {
     "@class": "org.apache.streampipes.model.connect.adapter.AdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription";
     dataSet: SpDataSet;
@@ -289,7 +305,7 @@
 }
 
 export class TransformationRuleDescription extends UnnamedStreamPipesEntity {
-    "@class": "org.apache.streampipes.model.connect.rules.TransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription" | "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.StreamTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.SchemaTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.CreateNestedRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription";
+    "@class": "org.apache.streampipes.model.connect.rules.TransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.StreamTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.SchemaTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.CreateNestedRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription" | "org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription";
 
     static fromData(data: TransformationRuleDescription, target?: TransformationRuleDescription): TransformationRuleDescription {
         if (!data) {
@@ -325,6 +341,8 @@
                 return RenameRuleDescription.fromData(data);
             case "org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription":
                 return MoveRuleDescription.fromData(data);
+            case "org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription":
+                return ChangeDatatypeTransformationRuleDescription.fromData(data);
             case "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription":
                 return CorrectionValueTransformationRuleDescription.fromData(data);
         }
@@ -332,7 +350,7 @@
 }
 
 export class ValueTransformationRuleDescription extends TransformationRuleDescription {
-    "@class": "org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription" | "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription";
+    "@class": "org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription" | "org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription" | "org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription" | "org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription";
 
     static fromData(data: ValueTransformationRuleDescription, target?: ValueTransformationRuleDescription): ValueTransformationRuleDescription {
         if (!data) {
@@ -588,6 +606,39 @@
     }
 }
 
+export class AssetExportConfiguration {
+    adapters: ExportItem[];
+    assetId: string;
+    assetName: string;
+    assets: ExportItem[];
+    dashboards: ExportItem[];
+    dataLakeMeasures: ExportItem[];
+    dataSources: ExportItem[];
+    dataViews: ExportItem[];
+    files: ExportItem[];
+    overrideBrokerSettings: boolean;
+    pipelines: ExportItem[];
+
+    static fromData(data: AssetExportConfiguration, target?: AssetExportConfiguration): AssetExportConfiguration {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new AssetExportConfiguration();
+        instance.assetId = data.assetId;
+        instance.assetName = data.assetName;
+        instance.assets = __getCopyArrayFn(ExportItem.fromData)(data.assets);
+        instance.adapters = __getCopyArrayFn(ExportItem.fromData)(data.adapters);
+        instance.dashboards = __getCopyArrayFn(ExportItem.fromData)(data.dashboards);
+        instance.dataViews = __getCopyArrayFn(ExportItem.fromData)(data.dataViews);
+        instance.dataLakeMeasures = __getCopyArrayFn(ExportItem.fromData)(data.dataLakeMeasures);
+        instance.dataSources = __getCopyArrayFn(ExportItem.fromData)(data.dataSources);
+        instance.pipelines = __getCopyArrayFn(ExportItem.fromData)(data.pipelines);
+        instance.files = __getCopyArrayFn(ExportItem.fromData)(data.files);
+        instance.overrideBrokerSettings = data.overrideBrokerSettings;
+        return instance;
+    }
+}
+
 export class BoundPipelineElement extends UnnamedStreamPipesEntity {
     "@class": "org.apache.streampipes.model.template.BoundPipelineElement";
     connectedTo: BoundPipelineElement[];
@@ -643,6 +694,25 @@
     }
 }
 
+export class ChangeDatatypeTransformationRuleDescription extends ValueTransformationRuleDescription {
+    "@class": "org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription";
+    originalDatatypeXsd: string;
+    runtimeKey: string;
+    targetDatatypeXsd: string;
+
+    static fromData(data: ChangeDatatypeTransformationRuleDescription, target?: ChangeDatatypeTransformationRuleDescription): ChangeDatatypeTransformationRuleDescription {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new ChangeDatatypeTransformationRuleDescription();
+        super.fromData(data, instance);
+        instance.runtimeKey = data.runtimeKey;
+        instance.originalDatatypeXsd = data.originalDatatypeXsd;
+        instance.targetDatatypeXsd = data.targetDatatypeXsd;
+        return instance;
+    }
+}
+
 export class CodeInputStaticProperty extends StaticProperty {
     "@class": "org.apache.streampipes.model.staticproperty.CodeInputStaticProperty";
     codeTemplate: string;
@@ -956,11 +1026,14 @@
 
 export class DataLakeMeasure extends UnnamedStreamPipesEntity {
     "@class": "org.apache.streampipes.model.datalake.DataLakeMeasure";
+    _rev: string;
     eventSchema: EventSchema;
     measureName: string;
     pipelineId: string;
     pipelineIsRunning: boolean;
     pipelineName: string;
+    schemaVersion: string;
+    timestampField: string;
 
     static fromData(data: DataLakeMeasure, target?: DataLakeMeasure): DataLakeMeasure {
         if (!data) {
@@ -969,10 +1042,13 @@
         const instance = target || new DataLakeMeasure();
         super.fromData(data, instance);
         instance.measureName = data.measureName;
+        instance.timestampField = data.timestampField;
         instance.eventSchema = EventSchema.fromData(data.eventSchema);
         instance.pipelineId = data.pipelineId;
         instance.pipelineName = data.pipelineName;
         instance.pipelineIsRunning = data.pipelineIsRunning;
+        instance.schemaVersion = data.schemaVersion;
+        instance._rev = data._rev;
         return instance;
     }
 }
@@ -1525,6 +1601,53 @@
     }
 }
 
+export class ExportConfiguration {
+    assetExportConfiguration: AssetExportConfiguration[];
+
+    static fromData(data: ExportConfiguration, target?: ExportConfiguration): ExportConfiguration {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new ExportConfiguration();
+        instance.assetExportConfiguration = __getCopyArrayFn(AssetExportConfiguration.fromData)(data.assetExportConfiguration);
+        return instance;
+    }
+}
+
+export class ExportItem {
+    label: string;
+    resourceId: string;
+    selected: boolean;
+
+    static fromData(data: ExportItem, target?: ExportItem): ExportItem {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new ExportItem();
+        instance.resourceId = data.resourceId;
+        instance.label = data.label;
+        instance.selected = data.selected;
+        return instance;
+    }
+}
+
+export class FieldStatusInfo {
+    additionalInfo: string;
+    changesRequired: boolean;
+    fieldStatus: FieldStatus;
+
+    static fromData(data: FieldStatusInfo, target?: FieldStatusInfo): FieldStatusInfo {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new FieldStatusInfo();
+        instance.fieldStatus = data.fieldStatus;
+        instance.additionalInfo = data.additionalInfo;
+        instance.changesRequired = data.changesRequired;
+        return instance;
+    }
+}
+
 export class FileMetadata {
     createdAt: number;
     createdByUser: string;
@@ -1696,7 +1819,9 @@
 
 export class GuessSchema extends UnnamedStreamPipesEntity {
     "@class": "org.apache.streampipes.model.connect.guess.GuessSchema";
+    eventPreview: { [index: string]: GuessTypeInfo }[];
     eventSchema: EventSchema;
+    fieldStatusInfo: { [index: string]: FieldStatusInfo };
 
     static fromData(data: GuessSchema, target?: GuessSchema): GuessSchema {
         if (!data) {
@@ -1705,6 +1830,23 @@
         const instance = target || new GuessSchema();
         super.fromData(data, instance);
         instance.eventSchema = EventSchema.fromData(data.eventSchema);
+        instance.eventPreview = __getCopyArrayFn(__getCopyObjectFn(GuessTypeInfo.fromData))(data.eventPreview);
+        instance.fieldStatusInfo = __getCopyObjectFn(FieldStatusInfo.fromData)(data.fieldStatusInfo);
+        return instance;
+    }
+}
+
+export class GuessTypeInfo {
+    type: string;
+    value: any;
+
+    static fromData(data: GuessTypeInfo, target?: GuessTypeInfo): GuessTypeInfo {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new GuessTypeInfo();
+        instance.type = data.type;
+        instance.value = data.value;
         return instance;
     }
 }
@@ -2500,9 +2642,9 @@
         const instance = target || new PipelineTemplateDescription();
         super.fromData(data, instance);
         instance.boundTo = __getCopyArrayFn(BoundPipelineElement.fromData)(data.boundTo);
-        instance.pipelineTemplateName = data.pipelineTemplateName;
-        instance.pipelineTemplateDescription = data.pipelineTemplateDescription;
         instance.pipelineTemplateId = data.pipelineTemplateId;
+        instance.pipelineTemplateDescription = data.pipelineTemplateDescription;
+        instance.pipelineTemplateName = data.pipelineTemplateName;
         return instance;
     }
 }
@@ -2911,6 +3053,7 @@
 
 export class SpQueryResult {
     allDataSeries: DataSeries[];
+    forId: string;
     headers: string[];
     sourceIndex: number;
     spQueryStatus: SpQueryStatus;
@@ -2926,6 +3069,7 @@
         instance.allDataSeries = __getCopyArrayFn(DataSeries.fromData)(data.allDataSeries);
         instance.sourceIndex = data.sourceIndex;
         instance.spQueryStatus = data.spQueryStatus;
+        instance.forId = data.forId;
         return instance;
     }
 }
@@ -3007,6 +3151,64 @@
     }
 }
 
+export class StreamPipesApplicationPackage {
+    adapters: string[];
+    assets: string[];
+    dashboardWidgets: string[];
+    dashboards: string[];
+    dataLakeMeasures: string[];
+    dataSources: string[];
+    dataViewWidgets: string[];
+    dataViews: string[];
+    files: string[];
+    pipelines: string[];
+    requiredAdapterAppIds: string[];
+    requiredDataSinkAppIds: string[];
+    requiredProcessorAppIds: string[];
+
+    static fromData(data: StreamPipesApplicationPackage, target?: StreamPipesApplicationPackage): StreamPipesApplicationPackage {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new StreamPipesApplicationPackage();
+        instance.requiredProcessorAppIds = __getCopyArrayFn(__identity<string>())(data.requiredProcessorAppIds);
+        instance.requiredDataSinkAppIds = __getCopyArrayFn(__identity<string>())(data.requiredDataSinkAppIds);
+        instance.requiredAdapterAppIds = __getCopyArrayFn(__identity<string>())(data.requiredAdapterAppIds);
+        instance.assets = __getCopyArrayFn(__identity<string>())(data.assets);
+        instance.adapters = __getCopyArrayFn(__identity<string>())(data.adapters);
+        instance.dashboards = __getCopyArrayFn(__identity<string>())(data.dashboards);
+        instance.dashboardWidgets = __getCopyArrayFn(__identity<string>())(data.dashboardWidgets);
+        instance.dataViews = __getCopyArrayFn(__identity<string>())(data.dataViews);
+        instance.dataViewWidgets = __getCopyArrayFn(__identity<string>())(data.dataViewWidgets);
+        instance.dataLakeMeasures = __getCopyArrayFn(__identity<string>())(data.dataLakeMeasures);
+        instance.dataSources = __getCopyArrayFn(__identity<string>())(data.dataSources);
+        instance.pipelines = __getCopyArrayFn(__identity<string>())(data.pipelines);
+        instance.files = __getCopyArrayFn(__identity<string>())(data.files);
+        return instance;
+    }
+}
+
+export class StreamPipesErrorMessage {
+    cause: string;
+    detail: string;
+    fullStackTrace: string;
+    level: string;
+    title: string;
+
+    static fromData(data: StreamPipesErrorMessage, target?: StreamPipesErrorMessage): StreamPipesErrorMessage {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new StreamPipesErrorMessage();
+        instance.level = data.level;
+        instance.title = data.title;
+        instance.detail = data.detail;
+        instance.cause = data.cause;
+        instance.fullStackTrace = data.fullStackTrace;
+        return instance;
+    }
+}
+
 export class SuccessMessage extends Message {
 
     static fromData(data: SuccessMessage, target?: SuccessMessage): SuccessMessage {
@@ -3259,6 +3461,8 @@
 
 export type EventStreamQualityDefinitionUnion = Frequency | Latency;
 
+export type FieldStatus = "GOOD" | "BAD" | "ATTENTION";
+
 export type MappingPropertyUnion = MappingPropertyNary | MappingPropertyUnary;
 
 export type MeasurementPropertyUnion = EventPropertyQualityDefinition | EventStreamQualityDefinition;
@@ -3283,7 +3487,7 @@
 
 export type TopicDefinitionUnion = SimpleTopicDefinition | WildcardTopicDefinition;
 
-export type TransformationRuleDescriptionUnion = AddTimestampRuleDescription | AddValueTransformationRuleDescription | TimestampTranfsformationRuleDescription | UnitTransformRuleDescription | EventRateTransformationRuleDescription | RemoveDuplicatesTransformationRuleDescription | CreateNestedRuleDescription | DeleteRuleDescription | RenameRuleDescription | MoveRuleDescription | CorrectionValueTransformationRuleDescription;
+export type TransformationRuleDescriptionUnion = AddTimestampRuleDescription | AddValueTransformationRuleDescription | TimestampTranfsformationRuleDescription | UnitTransformRuleDescription | EventRateTransformationRuleDescription | RemoveDuplicatesTransformationRuleDescription | CreateNestedRuleDescription | DeleteRuleDescription | RenameRuleDescription | MoveRuleDescription | ChangeDatatypeTransformationRuleDescription | CorrectionValueTransformationRuleDescription;
 
 export type TransportProtocolUnion = JmsTransportProtocol | KafkaTransportProtocol | MqttTransportProtocol;
 
diff --git a/ui/src/app/core-model/measurement-unit/MeasurementUnit.ts b/ui/projects/streampipes/platform-services/src/lib/model/measurement-unit/MeasurementUnit.ts
similarity index 100%
rename from ui/src/app/core-model/measurement-unit/MeasurementUnit.ts
rename to ui/projects/streampipes/platform-services/src/lib/model/measurement-unit/MeasurementUnit.ts
diff --git a/ui/projects/streampipes/platform-services/src/lib/query/data-view-query-generator.service.ts b/ui/projects/streampipes/platform-services/src/lib/query/data-view-query-generator.service.ts
index a4d1c73..97b64fc 100644
--- a/ui/projects/streampipes/platform-services/src/lib/query/data-view-query-generator.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/query/data-view-query-generator.service.ts
@@ -54,8 +54,7 @@
   generateQuery(startTime: number,
                 endTime: number,
                 sourceConfig: SourceConfig,
-                maximumResultingEvents: number = -1
-                ): DatalakeQueryParameters {
+                maximumResultingEvents: number = -1): DatalakeQueryParameters {
     const queryBuilder = DatalakeQueryParameterBuilder.create(startTime, endTime);
     const queryConfig = sourceConfig.queryConfig;
 
@@ -65,9 +64,9 @@
     );
 
     if (sourceConfig.queryConfig.groupBy !== undefined) {
-      const selectedGroupByFields = sourceConfig.queryConfig.groupBy.filter(field => field.selected);
+      const selectedGroupByFields = sourceConfig.queryConfig.groupBy.filter(field => field.selected === true);
       if (selectedGroupByFields.length > 0) {
-        queryBuilder.withGrouping(sourceConfig.queryConfig.groupBy);
+        queryBuilder.withGrouping(selectedGroupByFields);
       }
     }
 
@@ -75,6 +74,10 @@
       queryBuilder.withFilters(queryConfig.selectedFilters);
     }
 
+    if (queryConfig.order) {
+      queryBuilder.withOrdering(queryConfig.order);
+    }
+
     if (sourceConfig.queryType === 'single') {
       queryBuilder.withLimit(1);
     } else if (sourceConfig.queryType === 'raw') {
diff --git a/ui/projects/streampipes/platform-services/src/public-api.ts b/ui/projects/streampipes/platform-services/src/public-api.ts
index 7e959d8..e686a6e 100644
--- a/ui/projects/streampipes/platform-services/src/public-api.ts
+++ b/ui/projects/streampipes/platform-services/src/public-api.ts
@@ -24,10 +24,14 @@
 export * from './lib/platform-services.module';
 
 export * from './lib/apis/commons.service';
+export * from './lib/apis/adapter.service';
+export * from './lib/apis/asset-management.service';
 export * from './lib/apis/data-view-data-explorer.service';
 export * from './lib/apis/datalake-rest.service';
+export * from './lib/apis/dashboard.service';
 export * from './lib/apis/files.service';
 export * from './lib/apis/general-config.service';
+export * from './lib/apis/generic-storage.service';
 export * from './lib/apis/mail-config.service';
 export * from './lib/apis/measurement-units.service';
 export * from './lib/apis/permissions.service';
@@ -48,6 +52,7 @@
 export * from './lib/model/dashboard/dashboard.model';
 export * from './lib/model/email-config.model';
 export * from './lib/model/general-config.model';
+export * from './lib/model/measurement-unit/MeasurementUnit';
 export * from './lib/model/gen/streampipes-model-client';
 export * from './lib/model/gen/streampipes-model';
 
@@ -55,3 +60,5 @@
 export * from './lib/query/DatalakeQueryParameterBuilder';
 export * from './lib/query/data-view-query-generator.service';
 export * from './lib/model/user/user.model';
+
+export * from './lib/model/assets/asset.model';
diff --git a/ui/projects/streampipes/shared-ui/package.json b/ui/projects/streampipes/shared-ui/package.json
index 95c7477..8a55c7f 100644
--- a/ui/projects/streampipes/shared-ui/package.json
+++ b/ui/projects/streampipes/shared-ui/package.json
@@ -3,10 +3,13 @@
   "version": "0.0.1",
   "peerDependencies": {
     "@angular/animations": "^13.3.0",
+    "@angular/cdk": "^13.3.0",
     "@angular/common": "^13.3.0",
     "@angular/core": "^13.3.0",
+    "@angular/flex-layout": "^13.0.0-beta.38",
     "@angular/material": "^13.3.0",
-    "@angular/cdk": "^13.3.0",
+    "@angular/router": "^13.3.0",
+    "@streampipes/platform-services": "0.0.1",
     "rxjs": "^6.6.2"
   },
   "dependencies": {
diff --git a/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.html
similarity index 89%
rename from ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.html
rename to ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.html
index 79bf5a4..972c2a0 100644
--- a/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.html
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.html
@@ -16,4 +16,4 @@
   ~
   -->
 
-<pre>{{ eventSchema | json }}</pre>
\ No newline at end of file
+<div class="header-title title-left-border" [ngStyle]="{margin: margin}">{{title}}</div>
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.scss
similarity index 84%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.scss
index a375af7..f4e4f2d 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.scss
@@ -16,7 +16,13 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
+.title-left-border {
+  border-left: 4px solid var(--color-accent);
+  padding-left: 8px;
+}
+
+.header-title {
+  font-size: 20pt;
+  font-weight: bold;
 }
 
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.ts
similarity index 72%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
copy to ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.ts
index 4e64c25..6b27876 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-header-title/header-title.component.ts
@@ -17,20 +17,19 @@
  */
 
 import { Component, Input, OnInit } from '@angular/core';
-import { Notification } from '@streampipes/platform-services';
 
 @Component({
-  selector: 'sp-error-message',
-  templateUrl: './error-message.component.html',
-  styleUrls: ['./error-message.component.scss']
+  selector: 'sp-basic-header-title-component',
+  templateUrl: './header-title.component.html',
+  styleUrls: ['./header-title.component.scss']
 })
-export class ErrorMessageComponent implements OnInit {
+export class SpBasicHeaderTitleComponent implements OnInit {
 
-  @Input() errorMessages: Notification[];
+  @Input()
+  title: string;
 
-  showErrorMessage = false;
-
-  constructor() { }
+  @Input()
+  margin = '20px 0px';
 
   ngOnInit(): void {
   }
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.html
new file mode 100644
index 0000000..9d58bff
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.html
@@ -0,0 +1,32 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="column" fxFlex="100" class="panel-outer" [ngStyle]="{margin: outerMargin}">
+    <div class="general-panel-header" fxLayout="row" fxFlex="100" fxLayoutAlign="start center" *ngIf="!hideToolbar">
+        <div fxLayout="fill" fxFlex="100">
+            <div fxLayoutAlign="start center" fxLayout="row">
+            <div class="content-box-title" *ngIf="showTitle">{{panelTitle}}</div>
+            </div>
+            <ng-content select="[header]" fxFlex class="pr-5"></ng-content>
+        </div>
+    </div>
+
+    <div class="general-panel" [ngStyle]="{padding: innerPadding}">
+        <ng-content fxFlex="100"></ng-content>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.scss
similarity index 60%
copy from ui/src/app/connect/components/format-item-json/format-item-json.component.scss
copy to ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.scss
index 30123c0..c4d52df 100644
--- a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.scss
@@ -16,32 +16,32 @@
  *
  */
 
-
-.format-label {
-  line-height:50px;
-  margin: auto;
-  text-align: center;
-  font-weight: bold;
-  font-size: 1.3em;
+.panel-outer {
+  margin-top: 15px;
+  margin-bottom: 15px;
+  border: 2px solid var(--color-bg-3);
 }
 
-.format-box {
+.general-panel {
+  border: 0px solid var(--color-bg-3);
+}
+
+.general-panel-header {
+  margin-top: -1px;
+  background: var(--color-bg-2);
+  border: 0px solid var(--color-bg-3);
+  border-bottom: 2px solid var(--color-bg-3);
+  padding-left: 5px;
+  height: 50px;
   min-height: 50px;
-  box-shadow: 1px 1px 2px #555;
-  border: 1px solid gray;
-  cursor: pointer;
-  padding: 10px;
-  opacity: 0.7;
-  margin: 10px;
-  background: #ffffff;
+  max-height: 50px;
 }
 
-.format-box:hover {
-  opacity: 1;
+.content-box-title {
+  margin-left: 5px;
+  padding-left: 5px;
+  border-left: 4px solid var(--color-accent);
+  font-weight: 600;
+  font-size: 13pt;
+  white-space: nowrap;
 }
-
-.selectedItem {
-  opacity: 1;
-  background-color: grey;
-}
-
diff --git a/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.ts
similarity index 70%
rename from ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.ts
rename to ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.ts
index f80de67..3e56b98 100644
--- a/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-inner-panel/basic-inner-panel.component.ts
@@ -17,13 +17,27 @@
  */
 
 import { Component, Input } from '@angular/core';
-import { EventSchema } from '@streampipes/platform-services';
 
 @Component({
-    selector: 'sp-event-schema-preview',
-    templateUrl: './event-schema-preview.component.html',
-    styleUrls: ['./event-schema-preview.component.scss']
+  selector: 'sp-basic-inner-panel',
+  templateUrl: './basic-inner-panel.component.html',
+  styleUrls: ['./basic-inner-panel.component.scss']
 })
-export class EventSchemaPreviewComponent {
-    @Input() eventSchema: EventSchema;
+export class SpBasicInnerPanelComponent {
+
+  @Input()
+  panelTitle: string;
+
+  @Input()
+  showTitle = true;
+
+  @Input()
+  innerPadding = '15px';
+
+  @Input()
+  outerMargin = '0px';
+
+  @Input()
+  hideToolbar = false;
+
 }
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.html
new file mode 100644
index 0000000..12a4534
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.html
@@ -0,0 +1,50 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="column" class="page-container">
+    <div fxLayout="row" class="p-0 sp-bg-lightgray page-container-nav">
+            <div fxFlex="100" class="page-container-nav pr-5" fxLayout="row">
+                <div fxLayout="row"
+                     fxLayoutAlign="start center"
+                     style="border-right: 2px solid var(--color-bg-2)" *ngIf="showBackLink">
+                    <button mat-button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Back"
+                            (click)="navigateBack()"
+                            class="edit-menu-btn"
+                            data-cy="save-data-explorer-go-back-to-overview">
+                        <mat-icon>arrow_back</mat-icon>
+                    </button>
+                </div>
+                <nav mat-tab-nav-bar color="accent">
+                    <a mat-tab-link *ngFor="let item of spNavigationItems"
+                       (click)="navigateTo(item)"
+                       [active]="activeLink === item.itemId">
+                        <span class="upper-case">{{item.itemTitle}}</span>
+                    </a>
+                </nav>
+                <span fxFlex></span>
+                <ng-content select="[nav]" fxFlex="100" fxLayout="row" fxLayoutAlign="end center"></ng-content>
+            </div>
+    </div>
+
+    <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100">
+        <ng-content fxFlex="100"></ng-content>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.scss
similarity index 69%
copy from ui/src/app/connect/components/format-item-json/format-item-json.component.scss
copy to ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.scss
index 30123c0..4bbebfc 100644
--- a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.scss
@@ -16,32 +16,32 @@
  *
  */
 
-
-.format-label {
-  line-height:50px;
-  margin: auto;
-  text-align: center;
-  font-weight: bold;
-  font-size: 1.3em;
-}
-
-.format-box {
-  min-height: 50px;
-  box-shadow: 1px 1px 2px #555;
-  border: 1px solid gray;
-  cursor: pointer;
+.page-container-padding-inner {
   padding: 10px;
-  opacity: 0.7;
+}
+
+.sp-bg-lightgray {
+  background-color: var(--color-bg-1);
+}
+
+.sp-tab-bg {
+  background-color: var(--color-bg-1);
+}
+
+.page-container {
   margin: 10px;
-  background: #ffffff;
+  border: 1px solid var(--color-bg-3);
+  min-height: calc(100% - 50px);
 }
 
-.format-box:hover {
-  opacity: 1;
+.page-container-padding-inner {
+  margin: 10px;
 }
 
-.selectedItem {
-  opacity: 1;
-  background-color: grey;
+.upper-case {
+  text-transform: uppercase;
 }
 
+.pr-5 {
+  padding-right: 5px;
+}
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.ts
new file mode 100644
index 0000000..5ab53a5
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.ts
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input } from '@angular/core';
+import { Router } from '@angular/router';
+import { SpNavigationItem } from '../../models/sp-navigation.model';
+
+@Component({
+  selector: 'sp-basic-nav-tabs',
+  templateUrl: './basic-nav-tabs.component.html',
+  styleUrls: ['./basic-nav-tabs.component.scss']
+})
+export class SpBasicNavTabsComponent {
+
+  @Input()
+  spNavigationItems: SpNavigationItem[];
+
+  @Input()
+  activeLink: string;
+
+  @Input()
+  showBackLink = false;
+
+  @Input()
+  backLinkTarget: string[] = [];
+
+  constructor(private router: Router) {
+
+  }
+
+  navigateTo(spNavigationItem: SpNavigationItem) {
+    this.router.navigate(spNavigationItem.itemLink);
+  }
+
+  navigateBack() {
+    this.router.navigate(this.backLinkTarget);
+  }
+}
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.html
new file mode 100644
index 0000000..a8bf704
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.html
@@ -0,0 +1,43 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="column" class="page-container">
+    <div fxLayout="row" class="p-0 sp-bg-lightgray page-container-nav" *ngIf="!hideNavbar">
+        <div fxLayout="fill" fxFlex="100" class="pl-5 pr-5">
+            <div fxLayout="row"
+                 fxLayoutAlign="start center"
+                 style="border-right: 2px solid var(--color-bg-2)" *ngIf="showBackLink">
+                <button mat-button
+                        mat-icon-button
+                        color="accent"
+                        matTooltip="Back"
+                        (click)="navigateBack()"
+                        class="edit-menu-btn"
+                        data-cy="save-data-explorer-go-back-to-overview">
+                    <mat-icon>arrow_back</mat-icon>
+                </button>
+            </div>
+            <ng-content select="[nav]" fxFlex="100"></ng-content>
+        </div>
+    </div>
+
+    <div [ngClass]="padding ? 'page-container-padding-inner' : ''" fxLayout="column" fxFlex="100">
+        <ng-content fxFlex="100"></ng-content>
+    </div>
+</div>
+
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.scss
new file mode 100644
index 0000000..95d1ed5
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.scss
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+.fixed-height {
+  flex-direction: row;
+  box-sizing: border-box;
+  display: flex;
+  flex: 1 1 100%;
+  max-height: 100%;
+  overflow-y: auto;
+}
+
+.page-container-nav {
+  line-height:24px;
+  height: 50px;
+  border-bottom:1px solid var(--color-bg-3);
+}
+
+.sp-bg-lightgray {
+  background-color: var(--color-bg-1);
+}
+
+.sp-tab-bg {
+  background-color: var(--color-bg-1);
+}
+
+.page-container {
+  margin: 10px;
+  border: 1px solid var(--color-bg-3);
+  min-height: calc(100% - 50px);
+}
+
+.page-container-padding-inner {
+  margin: 20px;
+}
+
+.pl-5 {
+  padding-left: 5px;
+}
+
+.pr-5 {
+  padding-right: 5px;
+}
diff --git a/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.ts
similarity index 65%
copy from ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.ts
copy to ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.ts
index f80de67..12af9e3 100644
--- a/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-view/basic-view.component.ts
@@ -17,13 +17,32 @@
  */
 
 import { Component, Input } from '@angular/core';
-import { EventSchema } from '@streampipes/platform-services';
+import { Router } from '@angular/router';
 
 @Component({
-    selector: 'sp-event-schema-preview',
-    templateUrl: './event-schema-preview.component.html',
-    styleUrls: ['./event-schema-preview.component.scss']
+  selector: 'sp-basic-view',
+  templateUrl: './basic-view.component.html',
+  styleUrls: ['./basic-view.component.scss']
 })
-export class EventSchemaPreviewComponent {
-    @Input() eventSchema: EventSchema;
+export class SpBasicViewComponent {
+
+  @Input()
+  padding = false;
+
+  @Input()
+  showBackLink = false;
+
+  @Input()
+  backLinkTarget: string[];
+
+  @Input()
+  hideNavbar = false;
+
+  constructor(private router: Router) {
+
+  }
+
+  navigateBack() {
+    this.router.navigate(this.backLinkTarget);
+  }
 }
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.html
new file mode 100644
index 0000000..06dbd0c
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.html
@@ -0,0 +1,47 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-20">
+        <div fxFlex="100" fxLayout="column" class="mt-10">
+            <div *ngIf="title" fxLayoutAlign="start center" fxFlex="100" class="title-message color-warn">
+                <i class="material-icons color-warn" style="margin-right: 15px;">warning</i>
+                <span class="color-warn">{{title}}</span>
+            </div>
+            <div class="error-details-title">Probable cause</div>
+            <div class="log-message" [innerText]="message.cause">
+            </div>
+            <div class="mt-10">
+            <button mat-button color="accent" (click)="showDetails = !showDetails">Full details</button>
+            </div>
+            <div fxFlex="100" fxLayout="column" *ngIf="showDetails" class="mt-10">
+                <div class="error-details-title">Full stack trace</div>
+                <div class="log-message">
+                    <div [innerText]="message.fullStackTrace"></div>
+                </div>
+            </div>
+        </div>
+
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions actions-align-right">
+        <button mat-button mat-raised-button class="mat-basic" (click)="close()">
+            Close
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.scss
similarity index 60%
copy from ui/src/app/connect/components/format-item-json/format-item-json.component.scss
copy to ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.scss
index 30123c0..05d9cfd 100644
--- a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.scss
@@ -16,32 +16,40 @@
  *
  */
 
-
-.format-label {
-  line-height:50px;
-  margin: auto;
-  text-align: center;
-  font-weight: bold;
-  font-size: 1.3em;
-}
-
-.format-box {
-  min-height: 50px;
-  box-shadow: 1px 1px 2px #555;
-  border: 1px solid gray;
-  cursor: pointer;
+.log-message {
+  background-color: black;
+  font: 9pt Inconsolata, monospace;
+  text-shadow: 0 0 5px #C8C8C8;
+  color: white;
   padding: 10px;
-  opacity: 0.7;
-  margin: 10px;
-  background: #ffffff;
+  max-width: 100%;
+  min-height: 50px;
+  max-height: 300px;
+  overflow-y: scroll;
+  white-space: pre-wrap;
 }
 
-.format-box:hover {
-  opacity: 1;
+.error-details-title {
+  font-size: 13pt;
+  font-weight: var(--color-default-text);
+  border-left: 3px solid var(--color-accent);
+  padding-left: 10px;
+  margin-bottom: 15px;
 }
 
-.selectedItem {
-  opacity: 1;
-  background-color: grey;
+.mt-10 {
+  margin-top: 10px;
 }
 
+.p-20 {
+  padding: 20px;
+}
+
+.color-warn {
+  color: var(--color-warn);
+}
+
+.title-message {
+  font-size: 16pt;
+  margin-bottom: 15px;
+}
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.ts
new file mode 100644
index 0000000..b735d74
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component.ts
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import { StreamPipesErrorMessage } from '@streampipes/platform-services';
+import { DialogRef } from '../../../dialog/base-dialog/dialog-ref';
+
+@Component({
+  selector: 'sp-exception-details-dialog',
+  templateUrl: './exception-details-dialog.component.html',
+  styleUrls: ['./exception-details-dialog.component.scss', '../../../../../../../../src/scss/sp/sp-dialog.scss']
+})
+export class SpExceptionDetailsDialogComponent implements OnInit {
+
+  @Input()
+  message: StreamPipesErrorMessage;
+
+  @Input()
+  title: string;
+
+  showDetails = false;
+
+  constructor(private dialogRef: DialogRef<SpExceptionDetailsDialogComponent>) {
+
+  }
+
+  close() {
+    this.dialogRef.close();
+  }
+
+  ngOnInit(): void {
+    console.log(this.title);
+  }
+
+}
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.html
new file mode 100644
index 0000000..46238bf
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.html
@@ -0,0 +1,38 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="column" fxFlex="100" class="error-panel error">
+    <div fxLayout="row">
+        <div fxFlex="100" fxLayoutAlign="start center">
+            <div fxLayout="row" fxLayoutAlign="start center" class="p-5" fxFlex="100">
+                <div fxLayoutAlign="start center">
+                <i class="material-icons color-warn" style="margin-right: 15px;">warning</i>
+                <h5 fxFlex class="color-warn">{{message.title}}</h5>
+                </div>
+                <span fxFlex></span>
+                <div fxLayoutAlign="end center" *ngIf="showDetails">
+                    <button mat-button (click)="openDetailsDialog()">
+                        <i class="material-icons">visibility</i>&nbsp;Details
+                    </button>
+                </div>
+            </div>
+
+        </div>
+    </div>
+
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.scss
similarity index 82%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.scss
index 58ba04b..15a00db 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.scss
@@ -16,3 +16,15 @@
  *
  */
 
+.error-panel {
+  background: var(--color-bg-1);
+  border-radius: 5px;
+}
+
+.error {
+  border: 1px solid var(--color-warn);
+}
+
+.color-warn {
+  color: var(--color-warn);
+}
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.ts
new file mode 100644
index 0000000..2d78e1b
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/sp-exception-message/sp-exception-message.component.ts
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input } from '@angular/core';
+import { StreamPipesErrorMessage } from '@streampipes/platform-services';
+import { DialogService } from '../../dialog/base-dialog/base-dialog.service';
+import { PanelType } from '../../dialog/base-dialog/base-dialog.model';
+import { SpExceptionDetailsDialogComponent } from './exception-details-dialog/exception-details-dialog.component';
+
+@Component({
+  selector: 'sp-exception-message',
+  templateUrl: './sp-exception-message.component.html',
+  styleUrls: ['./sp-exception-message.component.scss']
+})
+export class SpExceptionMessageComponent {
+
+  @Input()
+  level = 'error';
+
+  @Input()
+  showDetails = true;
+
+  @Input()
+  message: StreamPipesErrorMessage;
+
+  constructor(private dialogService: DialogService) {
+
+  }
+
+  openDetailsDialog() {
+    this.dialogService.open(SpExceptionDetailsDialogComponent, {
+      panelType: PanelType.STANDARD_PANEL,
+      width: '80vw',
+      title: 'Error Details',
+      data: {
+        'message': this.message
+      }
+    });
+  }
+
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/projects/streampipes/shared-ui/src/lib/models/sp-navigation.model.ts
similarity index 81%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/projects/streampipes/shared-ui/src/lib/models/sp-navigation.model.ts
index 58ba04b..1a90c9e 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/projects/streampipes/shared-ui/src/lib/models/sp-navigation.model.ts
@@ -16,3 +16,13 @@
  *
  */
 
+export interface SpNavigationItem {
+  itemId: string;
+  itemTitle: string;
+  itemLink: string[];
+}
+
+export interface SpBreadcrumbItem {
+  label: string;
+  link?: string[];
+}
diff --git a/ui/projects/streampipes/shared-ui/src/lib/services/breadcrumb.service.ts b/ui/projects/streampipes/shared-ui/src/lib/services/breadcrumb.service.ts
new file mode 100644
index 0000000..1d915c6
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/services/breadcrumb.service.ts
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { BehaviorSubject } from 'rxjs';
+import { SpBreadcrumbItem } from '../models/sp-navigation.model';
+import { Injectable } from '@angular/core';
+
+@Injectable({providedIn: 'root'})
+export class SpBreadcrumbService {
+
+  currentNavHierarchy$: BehaviorSubject<SpBreadcrumbItem[]> = new BehaviorSubject<SpBreadcrumbItem[]>([]);
+
+  updateBreadcrumb(breadcrumbItems: SpBreadcrumbItem[]) {
+    this.currentNavHierarchy$.next(breadcrumbItems);
+  }
+
+  public getRootLink(baseRoute: SpBreadcrumbItem): SpBreadcrumbItem[] {
+    return [this.removeLink({...baseRoute})];
+  }
+
+  public makeRoute(baseItems: SpBreadcrumbItem[], label: string, link?: string[]) {
+    baseItems.push({label, link});
+    return baseItems;
+  }
+
+  public removeLink(item: SpBreadcrumbItem): SpBreadcrumbItem {
+    const newItem = {...item};
+    newItem.link = undefined;
+    return newItem;
+  }
+}
diff --git a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
index f7102fc..8e40ee5 100644
--- a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
@@ -24,21 +24,52 @@
 import { PortalModule } from '@angular/cdk/portal';
 import { MatButtonModule } from '@angular/material/button';
 import { OverlayModule } from '@angular/cdk/overlay';
+import { SpBasicViewComponent } from './components/basic-view/basic-view.component';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { MatIconModule } from '@angular/material/icon';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { SpBasicNavTabsComponent } from './components/basic-nav-tabs/basic-nav-tabs.component';
+import { MatTabsModule } from '@angular/material/tabs';
+import { SpBasicInnerPanelComponent } from './components/basic-inner-panel/basic-inner-panel.component';
+import { SpBasicHeaderTitleComponent } from './components/basic-header-title/header-title.component';
+import { SpExceptionMessageComponent } from './components/sp-exception-message/sp-exception-message.component';
+import { SpExceptionDetailsDialogComponent } from './components/sp-exception-message/exception-details-dialog/exception-details-dialog.component';
+import { MatDividerModule } from '@angular/material/divider';
 
 @NgModule({
   declarations: [
     ConfirmDialogComponent,
     PanelDialogComponent,
-    StandardDialogComponent
+    StandardDialogComponent,
+    SpBasicInnerPanelComponent,
+    SpBasicHeaderTitleComponent,
+    SpBasicViewComponent,
+    SpBasicNavTabsComponent,
+    SpExceptionMessageComponent,
+    SpExceptionDetailsDialogComponent
   ],
   imports: [
     CommonModule,
-    PortalModule,
+    FlexLayoutModule,
     MatButtonModule,
-    OverlayModule
+    MatDividerModule,
+    MatIconModule,
+    MatTabsModule,
+    MatTooltipModule,
+    PortalModule,
+    OverlayModule,
   ],
   exports: [
-    ConfirmDialogComponent, PanelDialogComponent, StandardDialogComponent
+    ConfirmDialogComponent,
+    PanelDialogComponent,
+    StandardDialogComponent,
+    SpBasicInnerPanelComponent,
+    SpBasicHeaderTitleComponent,
+    SpBasicViewComponent,
+    SpBasicNavTabsComponent,
+    SpExceptionMessageComponent,
+    SpExceptionDetailsDialogComponent
   ]
 })
-export class SharedUiModule { }
+export class SharedUiModule {
+}
diff --git a/ui/projects/streampipes/shared-ui/src/public-api.ts b/ui/projects/streampipes/shared-ui/src/public-api.ts
index b7b26ed..a19dfd5 100644
--- a/ui/projects/streampipes/shared-ui/src/public-api.ts
+++ b/ui/projects/streampipes/shared-ui/src/public-api.ts
@@ -19,7 +19,6 @@
 export * from './lib/shared-ui.module';
 
 export * from './lib/dialog/base-dialog/base-dialog.model';
-// export * from './lib/dialog/base-dialog/base-dialog.component';
 export * from './lib/dialog/base-dialog/base-dialog.service';
 export * from './lib/dialog/base-dialog/dialog-ref';
 
@@ -27,4 +26,15 @@
 export * from './lib/dialog/panel-dialog/panel-dialog.component';
 export * from './lib/dialog/standard-dialog/standard-dialog.component';
 
+export * from './lib/components/basic-header-title/header-title.component';
+export * from './lib/components/basic-inner-panel/basic-inner-panel.component';
+export * from './lib/components/basic-view/basic-view.component';
+export * from './lib/components/basic-nav-tabs/basic-nav-tabs.component';
+export * from './lib/components/sp-exception-message/sp-exception-message.component';
+export * from './lib/components/sp-exception-message/exception-details-dialog/exception-details-dialog.component';
+
+export * from './lib/models/sp-navigation.model';
+
+export * from './lib/services/breadcrumb.service';
+
 
diff --git a/ui/src/app/_enums/page-name.enum.ts b/ui/src/app/_enums/page-name.enum.ts
index 472780a..a681bcc 100644
--- a/ui/src/app/_enums/page-name.enum.ts
+++ b/ui/src/app/_enums/page-name.enum.ts
@@ -30,4 +30,5 @@
   FILE_UPLOAD,
   PROFILE,
   SETTINGS,
+  ASSETS
 }
diff --git a/ui/src/app/add/add.component.html b/ui/src/app/add/add.component.html
index 63c025a..0c75094 100644
--- a/ui/src/app/add/add.component.html
+++ b/ui/src/app/add/add.component.html
@@ -16,61 +16,59 @@
   ~
   -->
 
-<div fxLayout="column" class="page-container">
-    <div fxLayout="row" class="border sp-bg-lightgray p-0">
-        <div fxFlex="100" class="page-container-nav">
-            <div fxFlex="100" fxLayout="row">
-                <button mat-button mat-flat-button color="accent" (click)="showManageRdfEndpointsDialog()">Manage
-                    Endpoints
-                </button>
-                <div fxFlex fxLayoutAlign="start center" [attr.id]="'peType'">
-                    <mat-tab-group [selectedIndex]="selectedCategoryIndex"
-                                   (selectedIndexChange)="setSelectedTab($event)" color="accent">
-                        <mat-tab label="All"></mat-tab>
-                        <mat-tab label="Data Sets"></mat-tab>
-                        <mat-tab label="Data Streams"></mat-tab>
-                        <mat-tab label="Data Processors"></mat-tab>
-                        <mat-tab label="Data Sinks"></mat-tab>
-                    </mat-tab-group>
-                </div>
-            </div>
-        </div>
-    </div>
-    <div fxLayout="row" class="fixed-height add-options sp-tab-bg">
-        <div class="add-options-item pl-5" fxLayoutAlign="start center" fxLayout="row">
-            <div fxFlex="100" fxLayout="row">
-                <button mat-button mat-raised-button color="accent"
-                        [disabled]="selectedEndpointItems.length === 0"
-                        (click)="installSelected()" class="mr-10">
-                    <i class="material-icons">cloud_download</i>
-                    &nbsp;Install selected
-                </button>
-                <button mat-button mat-raised-button color="accent"
-                        [disabled]="selectedEndpointItems.length === 0"
-                        (click)="uninstallSelected()" class="mr-10">
-                    <i class="material-icons">delete</i>
-                    &nbsp;Uninstall selected
-                </button>
-                <button mat-button mat-icon-button color="accent" class="mr-10" (click)="selectAll(true)"
-                        matTooltip="Select all" matTooltipPosition="above">
-                    <i class="material-icons">queue</i>
-                </button>
-                <button mat-button mat-icon-button color="accent" class="mr-10" (click)="selectAll(false)"
-                        matTooltip="Select none" matTooltipPosition="above">
-                    <i class="material-icons">filter_none</i>
-                </button>
-            </div>
+<sp-basic-view [showBackLink]="false" [padding]="true">
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <div fxFlex="100" fxLayout="row">
+            <button mat-button mat-raised-button color="accent" [disabled]="selectedEndpointItems.length === 0"
+                    (click)="installSelected()" class="mr-10">
+                <i class="material-icons">cloud_download</i>
+                &nbsp;Install selected
+            </button>
+            <button mat-button mat-raised-button color="accent" [disabled]="selectedEndpointItems.length === 0"
+                    (click)="uninstallSelected()" class="mr-10">
+                <i class="material-icons">delete</i>
+                &nbsp;Uninstall selected
+            </button>
+            <button mat-button mat-icon-button color="accent" class="mr-10" (click)="selectAll(true)"
+                    matTooltip="Select all" matTooltipPosition="above">
+                <i class="material-icons">queue</i>
+            </button>
+            <button mat-button mat-icon-button color="accent" class="mr-10" (click)="selectAll(false)"
+                    matTooltip="Select none" matTooltipPosition="above">
+                <i class="material-icons">filter_none</i>
+            </button>
         </div>
         <span fxFlex></span>
-        <div class="add-options-item pl-5" fxLayoutAlign="start center" fxLayout="row">
-            <mat-icon>search</mat-icon>
-
-            <mat-form-field class="form-style" color="accent">
-                <input matInput placeholder="Find Element" value="" [(ngModel)]="filterTerm"
-                       name="something">
+        <div fxLayoutAlign="start center" fxLayout="row">
+            <mat-form-field color="accent">
+                <mat-select [(value)]="selectedCategory"
+                            (selectionChange)="filterByCatergory($event)">
+                    <mat-option [value]="'all'">
+                        All
+                    </mat-option>
+                    <mat-option [value]="'set'">
+                        Sets
+                    </mat-option>
+                    <mat-option [value]="'stream'">
+                        Streams
+                    </mat-option>
+                    <mat-option [value]="'sepa'">
+                        Processors
+                    </mat-option>
+                    <mat-option [value]="'action'">
+                        Sinks
+                    </mat-option>
+                </mat-select>
             </mat-form-field>
         </div>
-        <div class="add-options-item" fxLayoutAlign="start center" fxLayout="row">
+        <div class="ml-10" fxLayoutAlign="start center" fxLayout="row">
+            <mat-icon>search</mat-icon>
+
+            <mat-form-field class="form-style" color="accent" floatLabel="never">
+                <input matInput placeholder="Find Element" value="" [(ngModel)]="filterTerm" name="something">
+            </mat-form-field>
+        </div>
+        <div fxLayoutAlign="start center" fxLayout="row" class="ml-10">
             <mat-form-field color="accent">
                 <mat-select [(value)]="selectedInstallationStatus">
                     <mat-option [value]="'all'">
@@ -85,31 +83,35 @@
                 </mat-select>
             </mat-form-field>
         </div>
-        <div class="add-options-item" fxLayoutAlign="start center" fxLayout="row">
-            <button mat-button mat-icon-button color="accent" (click)="getEndpointItems()"
-                    matTooltip="Reload items" matTooltipPosition="above">
+        <div fxLayoutAlign="start center" fxLayout="row" class="ml-10">
+            <button mat-button mat-icon-button color="accent" (click)="getEndpointItems()" matTooltip="Reload items"
+                    matTooltipPosition="above">
                 <mat-icon>refresh</mat-icon>
             </button>
         </div>
+        <button mat-button mat-icon-button color="accent" (click)="showManageRdfEndpointsDialog()"
+                matTooltip="Manage Endpoints">
+            <i class="material-icons">settings</i>
+        </button>
     </div>
+    <div fxLayout="column" fxFlex="100">
 
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="page-container-padding-inner"
-         *ngIf="endpointItemsLoadingComplete">
-        <div fxLayoutAlign="start start" fxLayout="column">
 
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start"
+             *ngIf="endpointItemsLoadingComplete">
+            <div fxLayoutAlign="start start" fxLayout="column">
+                <sp-basic-header-title-component title="Available Pipeline Elements"></sp-basic-header-title-component>
+            </div>
+            <div fxLayout="row wrap" class="w-100">
+                <sp-endpoint-item fxFlex="33" [itemSelected]="endpointItem.selected" [item]="endpointItem"
+                                  (triggerInstallation)="triggerInstallation($event)"
+                                  *ngFor="let endpointItem of endpointItems | pipelineElementTypeFilter: selectedTab | pipelineElementNameFilter: filterTerm | pipelineElementInstallationStatusFilter: selectedInstallationStatus | orderBy: 'asc':'name'"
+                                  class="p-15" (click)="toggleSelected(endpointItem)"></sp-endpoint-item>
+            </div>
         </div>
-        <div fxLayout="row wrap" class="w-100">
-            <sp-endpoint-item fxFlex="33"
-                              [itemSelected]="endpointItem.selected"
-                              [item]="endpointItem"
-                              (triggerInstallation)="triggerInstallation($event)"
-                              *ngFor="let endpointItem of endpointItems | pipelineElementTypeFilter: selectedTab | pipelineElementNameFilter: filterTerm | pipelineElementInstallationStatusFilter: selectedInstallationStatus | orderBy: 'asc':'name'"
-                              class="p-15"
-                              (click)="toggleSelected(endpointItem)"></sp-endpoint-item>
+        <div fxFlex="100" fxLayout="row" fxLayoutAlign="center center" *ngIf="!endpointItemsLoadingComplete">
+            <mat-spinner [mode]="'indeterminate'" [diameter]="20" color="accent"></mat-spinner>
+            <h4>&nbsp;&nbsp;Searching for available pipeline elements, please wait...</h4>
         </div>
     </div>
-    <div fxFlex="100" fxLayout="row" fxLayoutAlign="center center" *ngIf="!endpointItemsLoadingComplete">
-        <mat-spinner [mode]="'indeterminate'" [diameter]="20" color="accent"></mat-spinner>
-        <h4>&nbsp;&nbsp;Searching for available pipeline elements, please wait...</h4>
-    </div>
-</div>
+</sp-basic-view>
diff --git a/ui/src/app/add/add.component.scss b/ui/src/app/add/add.component.scss
index b641e78..ffe023f 100644
--- a/ui/src/app/add/add.component.scss
+++ b/ui/src/app/add/add.component.scss
@@ -30,6 +30,10 @@
   margin-right: 10px;
 }
 
+.ml-10 {
+  margin-left: 10px;
+}
+
 .add-options {
   padding:0px;
   border-bottom: 1px solid var(--color-bg-2);
diff --git a/ui/src/app/add/add.component.ts b/ui/src/app/add/add.component.ts
index 7df4a35..62e5e3f 100644
--- a/ui/src/app/add/add.component.ts
+++ b/ui/src/app/add/add.component.ts
@@ -16,13 +16,14 @@
  *
  */
 
-import { RestApi } from '../services/rest-api.service';
 import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
 import { AddService } from './services/add.service';
-import { DialogRef, DialogService, PanelType } from '@streampipes/shared-ui';
+import { DialogRef, DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
 import { AddEndpointComponent } from './dialogs/add-endpoint/add-endpoint.component';
 import { EndpointInstallationComponent } from './dialogs/endpoint-installation/endpoint-installation.component';
 import { ExtensionsServiceEndpointItem } from '@streampipes/platform-services';
+import { Router } from '@angular/router';
+import { SpAddRoutes } from './add.routes';
 
 @Component({
     selector: 'sp-add',
@@ -31,6 +32,8 @@
 })
 export class AddComponent implements OnInit {
 
+    activeLink: string;
+
     results: any[];
     loading: boolean;
     endpointItems: ExtensionsServiceEndpointItem[];
@@ -39,16 +42,18 @@
     availableTypes: string[] = ['all', 'set', 'stream', 'sepa', 'action'];
 
     selectedCategoryIndex = 0;
+    selectedCategory = 'all';
 
     selectedEndpointItems: any[] = [];
 
     _filterTerm = '';
     _selectedInstallationStatus = 'all';
 
-    constructor(private restApi: RestApi,
-                private addService: AddService,
+    constructor(private addService: AddService,
                 private dialogService: DialogService,
-                private changeDetectorRef: ChangeDetectorRef) {
+                private changeDetectorRef: ChangeDetectorRef,
+                private router: Router,
+                private breadcrumbService: SpBreadcrumbService) {
         this.results = [];
         this.loading = false;
         this.endpointItems = [];
@@ -56,6 +61,7 @@
     }
 
     ngOnInit() {
+        this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpAddRoutes.BASE));
         this.getEndpointItems();
         this.selectedTab = 'all';
     }
@@ -81,6 +87,10 @@
         return endpointItem.selected;
     }
 
+    filterByCatergory(category) {
+        this.selectedTab = category.value;
+    }
+
     selectAll(selected) {
         this.selectedEndpointItems = [];
         this.endpointItems.forEach(item => {
@@ -95,20 +105,7 @@
         });
         this.changeDetectorRef.detectChanges();
     }
-
-    getTitle(selectedTab) {
-        if (selectedTab === 'source') {
-            return 'Data Sources';
-        } else if (selectedTab === 'sepa') {
-            return 'Processing Elements';
-        } else if (selectedTab === 'action') {
-            return 'Data Sinks';
-        } else if (selectedTab === 'all') {
-            return 'All Pipeline Elements';
-        } else {
-            return 'Marketplace';
-        }
-    }
+    
 
     showManageRdfEndpointsDialog() {
         const dialogRef: DialogRef<AddEndpointComponent> = this.dialogService.open(AddEndpointComponent, {
@@ -195,4 +192,9 @@
     get selectedInstallationStatus(): string {
         return this._selectedInstallationStatus;
     }
+
+    navigateTo(routeId: string): void {
+      this.router.navigate(['add', routeId]);
+      this.activeLink = routeId;
+    }
 }
diff --git a/ui/src/app/add/add.module.ts b/ui/src/app/add/add.module.ts
index 176ee2d..9c91e7d 100644
--- a/ui/src/app/add/add.module.ts
+++ b/ui/src/app/add/add.module.ts
@@ -33,6 +33,8 @@
 import { EndpointInstallationComponent } from './dialogs/endpoint-installation/endpoint-installation.component';
 import { PipelineElementNameFilter } from './filter/pipeline-element-name.pipe';
 import { PipelineElementInstallationStatusFilter } from './filter/pipeline-element-installation-status.pipe';
+import { RouterModule } from "@angular/router";
+import { SharedUiModule } from '../../../projects/streampipes/shared-ui/src/lib/shared-ui.module';
 
 
 @NgModule({
@@ -44,6 +46,18 @@
     CoreUiModule,
     CustomMaterialModule,
     MatProgressSpinnerModule,
+    RouterModule.forChild([
+      {
+        path: 'add',
+        children: [
+          {
+            path: '',
+            component: AddComponent
+          }
+        ]
+      }
+    ]),
+    SharedUiModule
   ],
   declarations: [
     AddComponent,
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/add/add.routes.ts
similarity index 77%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/add/add.routes.ts
index 58ba04b..a035fea 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/add/add.routes.ts
@@ -16,3 +16,10 @@
  *
  */
 
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+
+export class SpAddRoutes {
+
+  static ADD_BASE_LINK = 'add';
+  static BASE: SpBreadcrumbItem = {label: 'Install Pipeline Elements', link: [SpAddRoutes.ADD_BASE_LINK]};
+}
diff --git a/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.html b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.html
index 6dd1064..2b9c7cf 100644
--- a/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.html
+++ b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.html
@@ -50,7 +50,7 @@
             </div>
         </div>
         <div style="margin-top:10px;">
-            <button mat-button mat-raised-button color="accent" (click)="showAddInput()">Add Category</button>
+            <button mat-button mat-raised-button color="accent" (click)="showAddInput()">Add Endpoint</button>
         </div>
     </div>
     <mat-divider></mat-divider>
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
index 13dae74..8026958 100644
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
+++ b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
@@ -16,21 +16,19 @@
   ~
   -->
 
-<div fxLayout="column" fxFlex="100" class="page-container-connect">
-    <div fxLayout="row" class="sp-tab-bg">
-        <div fxLayout="fill" class="page-container-nav">
-            <mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="selectedIndexChange($event)" color="accent">
-                <mat-tab label="Asset Dashboards">
-                </mat-tab>
-                <mat-tab id="all-adapters" label="New Asset Dashboard">
-                </mat-tab>
-            </mat-tab-group>
-        </div>
-    </div>
+<sp-basic-view showBackLink="true" [backLinkTarget]="['apps']">
+    <ng-container nav>
+        <mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="selectedIndexChange($event)" color="accent">
+            <mat-tab label="Asset Dashboards">
+            </mat-tab>
+            <mat-tab id="all-adapters" label="New Asset Dashboard">
+            </mat-tab>
+        </mat-tab-group>
+    </ng-container>
 
     <div fxLayout="column" fxFlex="100">
-        <sp-asset-dashboard-overview *ngIf="selectedIndex == 0 && !dashboardSelected" fxFlex="100" (selectedDashboard)="openDashboard($event)"></sp-asset-dashboard-overview>
+        <sp-asset-dashboard-overview *ngIf="selectedIndex == 0 && !dashboardSelected" fxFlex="100" (selectedDashboard)="openDashboard($event)" (createDashboard)="selectedIndex = 1"></sp-asset-dashboard-overview>
         <sp-view-asset fxFlex="100" *ngIf="selectedIndex == 0 && dashboardSelected" [dashboardConfig]="selectedDashboard" (dashboardClosed)="closeDashboard($event)" (editDashboardEmitter)="editDashboard($event)"></sp-view-asset>
         <sp-create-asset *ngIf="selectedIndex == 1" fxFlex="100" (dashboardClosed)="closeDashboard($event)" [dashboardConfig]="selectedDashboard"></sp-create-asset>
     </div>
-</div>
+</sp-basic-view>
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.ts b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.ts
index b0e7a31..3d9542a 100644
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.ts
+++ b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.ts
@@ -18,6 +18,9 @@
 
 import { Component, EventEmitter, OnInit, Output } from '@angular/core';
 import { DashboardConfiguration } from './model/dashboard-configuration.model';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpAppRoutes } from '../app-overview/apps.routes';
+import { SpAppAssetMonitoringRoutes } from './app-asset-monitoring.routes';
 
 @Component({
     selector: 'sp-app-asset-monitoring',
@@ -32,11 +35,12 @@
     selectedDashboard: DashboardConfiguration;
     @Output() appOpened = new EventEmitter<boolean>();
 
-    constructor() {
+    constructor(private breadcrumbService: SpBreadcrumbService) {
 
     }
 
     ngOnInit() {
+        this.breadcrumbService.updateBreadcrumb([SpAppRoutes.BASE, this.breadcrumbService.removeLink(SpAppAssetMonitoringRoutes.BASE)]);
         this.appOpened.emit(true);
     }
 
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts b/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
index a2882c5..215705e 100644
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
+++ b/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
@@ -39,36 +39,45 @@
 import { AssetDashboardOverviewComponent } from './components/dashboard-overview/dashboard-overview.component';
 import { AddLinkDialogComponent } from './dialog/add-link/add-link-dialog.component';
 import { DashboardModule } from '../dashboard/dashboard.module';
+import { RouterModule } from '@angular/router';
+import { SharedUiModule } from '@streampipes/shared-ui';
 
 @NgModule({
-    imports: [
-        CommonModule,
-        FlexLayoutModule,
-        CustomMaterialModule,
-        MatGridListModule,
-        MatInputModule,
-        MatFormFieldModule,
-        FormsModule,
-        ColorPickerModule,
-        DashboardModule
-    ],
-    declarations: [
-        AppAssetMonitoringComponent,
-        CreateAssetComponent,
-        ViewAssetComponent,
-        AddLinkDialogComponent,
-        AddPipelineDialogComponent,
-        SaveDashboardDialogComponent,
-        AssetDashboardOverviewComponent
-    ],
-    providers: [
-        RestService,
-        ShapeService,
-        ElementIconText
-    ],
-    exports: [
-        AppAssetMonitoringComponent
-    ]
+  imports: [
+    CommonModule,
+    FlexLayoutModule,
+    CustomMaterialModule,
+    MatGridListModule,
+    MatInputModule,
+    MatFormFieldModule,
+    FormsModule,
+    ColorPickerModule,
+    DashboardModule,
+    RouterModule.forChild([
+      {
+        path: '',
+        component: AppAssetMonitoringComponent
+      }
+    ]),
+    SharedUiModule
+  ],
+  declarations: [
+    AppAssetMonitoringComponent,
+    CreateAssetComponent,
+    ViewAssetComponent,
+    AddLinkDialogComponent,
+    AddPipelineDialogComponent,
+    SaveDashboardDialogComponent,
+    AssetDashboardOverviewComponent
+  ],
+  providers: [
+    RestService,
+    ShapeService,
+    ElementIconText
+  ],
+  exports: [
+    AppAssetMonitoringComponent
+  ]
 })
 export class AppAssetMonitoringModule {
 }
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/app-asset-monitoring/app-asset-monitoring.routes.ts
similarity index 73%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/app-asset-monitoring/app-asset-monitoring.routes.ts
index 58ba04b..13b9f4c 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/app-asset-monitoring/app-asset-monitoring.routes.ts
@@ -16,3 +16,10 @@
  *
  */
 
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+import { SpAppRoutes } from '../app-overview/apps.routes';
+
+export class SpAppAssetMonitoringRoutes {
+
+  static BASE: SpBreadcrumbItem = {label: 'Asset Monitoring', link: [SpAppRoutes.APP_BASE_LINK, 'asset-monitoring']};
+}
diff --git a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.html b/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.html
index 3c38093..90b7037 100644
--- a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.html
+++ b/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.html
@@ -20,7 +20,7 @@
     <h1>Asset Dashboards</h1>
     <mat-grid-list
             [cols]="3" [rowHeight]="500"
-            [gutterSize]="10" fxFlex="100">
+            [gutterSize]="10" fxFlex="100" *ngIf="dashboardConfigs.length > 0">
 
         <mat-grid-tile class="gray" *ngFor="let dashboardConfig of dashboardConfigs">
 
@@ -41,7 +41,8 @@
             </mat-card>
         </mat-grid-tile>
     </mat-grid-list>
-    <div *ngIf="dashboardConfigs.length == 0">
-        <h4>(no dashboards available, navigate to <i>New Dashboard</i> to create a new asset dashboard)</h4>
+    <div *ngIf="dashboardConfigs.length == 0" fxLayoutAlign="center center" fxFlex="100" fxLayout="column">
+        <h4>No asset dashboards available</h4>
+        <button mat-button mat-raised-button color="accent" style="margin-top: 10px;" (click)="createDashboard.emit()">Create new</button>
     </div>
 </div>
diff --git a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.ts b/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.ts
index 57b0a6f..65e7a9c 100644
--- a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.ts
+++ b/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.ts
@@ -28,6 +28,7 @@
 export class AssetDashboardOverviewComponent implements OnInit {
 
     @Output() selectedDashboard = new EventEmitter<DashboardConfiguration>();
+    @Output() createDashboard = new EventEmitter<void>();
 
     dashboardConfigs: DashboardConfiguration[] = [];
 
diff --git a/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.ts b/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.ts
index 8a88fbf..ca435e3 100644
--- a/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.ts
+++ b/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.ts
@@ -21,8 +21,7 @@
 import Konva from 'konva';
 import { DashboardConfiguration } from '../../model/dashboard-configuration.model';
 import { RestService } from '../../services/rest.service';
-import { DashboardService } from '../../../dashboard/services/dashboard.service';
-import { DatalakeQueryParameterBuilder, DatalakeRestService, SpQueryResult } from '@streampipes/platform-services';
+import { DatalakeQueryParameterBuilder, DatalakeRestService, SpQueryResult, DashboardService } from '@streampipes/platform-services';
 import { Subscription, timer } from 'rxjs';
 import { switchMap } from 'rxjs/operators';
 
diff --git a/ui/src/app/app-overview/app-overview.component.html b/ui/src/app/app-overview/app-overview.component.html
index 9085fd3..40ad6e2 100644
--- a/ui/src/app/app-overview/app-overview.component.html
+++ b/ui/src/app/app-overview/app-overview.component.html
@@ -16,39 +16,27 @@
   ~
   -->
 
-<div fxLayout="column" class="page-container page-container-connect">
-    <div fxLayout="row" class="sp-tab-bg">
-        <div fxLayoutAlign="end center" fxLayout="fill" class="page-container-nav"
-             style="padding-right:10px; width:100%;min-height:50px;line-height:24px;margin-bottom:1px;">
-            <div *ngIf="appOpen">
-                <button mat-button mat-raised-button color="accent" (click)="appClosed()">
-                    Close App
-                </button>
-            </div>
-        </div>
-    </div>
+<sp-basic-view padding="true">
+    <ng-container nav>
 
-    <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100" *ngIf="!appOpen">
-        <div fxFlex="100" fxLayout="column">
-            <h1>My apps</h1>
-            <mat-card class="example-card" *ngFor="let app of apps">
-                <div fxFlex="100" fxLayout="row">
-                    <div fxFlex="75" fxLayout="column" fxLayoutAlign="center start">
-                        <mat-card-header>
-                            <mat-card-title> {{app.appName}}</mat-card-title>
-                            <mat-card-subtitle>{{app.appDescription}}</mat-card-subtitle>
-                        </mat-card-header>
-                    </div>
-                    <div fxFlex="25" fxLayoutAlign="center end" fxLayout="column">
-                        <button mat-button mat-raised-button color="accent" (click)="selectApp(app.appId)">Open App
-                        </button>
-                    </div>
+    </ng-container>
+
+
+    <div fxFlex="100" fxLayout="column">
+        <sp-basic-header-title-component title="My apps"></sp-basic-header-title-component>
+        <mat-card class="example-card" *ngFor="let app of apps">
+            <div fxFlex="100" fxLayout="row">
+                <div fxFlex="75" fxLayout="column" fxLayoutAlign="center start">
+                    <mat-card-header>
+                        <mat-card-title> {{app.appName}}</mat-card-title>
+                        <mat-card-subtitle>{{app.appDescription}}</mat-card-subtitle>
+                    </mat-card-header>
                 </div>
-            </mat-card>
-        </div>
+                <div fxFlex="25" fxLayoutAlign="center end" fxLayout="column">
+                    <button mat-button mat-raised-button color="accent" (click)="selectApp(app.appLink)">Open App
+                    </button>
+                </div>
+            </div>
+        </mat-card>
     </div>
-    <div class="fixed-height" fxLayout="column" fxFlex="100">
-    <sp-app-asset-monitoring (appOpened)="appOpened($event)"
-                             *ngIf="currentlySelectedApp === apps[0].appId"></sp-app-asset-monitoring>
-    </div>
-</div>
+</sp-basic-view>
diff --git a/ui/src/app/app-overview/app-overview.component.ts b/ui/src/app/app-overview/app-overview.component.ts
index d89f93b..8c0aaa6 100644
--- a/ui/src/app/app-overview/app-overview.component.ts
+++ b/ui/src/app/app-overview/app-overview.component.ts
@@ -17,6 +17,11 @@
  */
 
 import { Component, OnInit } from '@angular/core';
+import { App } from './apps.model';
+import { AvailableAppsService } from './apps';
+import { Router } from '@angular/router';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpAppRoutes } from './apps.routes';
 
 @Component({
     templateUrl: './app-overview.component.html',
@@ -24,41 +29,20 @@
 })
 export class AppOverviewComponent implements OnInit {
 
-    selectedIndex = 0;
-    appOpen = false;
-    currentlySelectedApp = '';
+    apps: App[] = [];
 
-    apps: any[] = [
-        {
-            appName: 'Asset Dashboards',
-            appDescription: 'Monitor measurements of your assets by placing visualizations on an image of your asset.',
-            appId: 'asset-monitoring',
-        }
-    ];
-
-    constructor() {
+    constructor(private router: Router,
+                private breadcrumbService: SpBreadcrumbService) {
 
     }
 
     ngOnInit() {
-
+        this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpAppRoutes.BASE));
+        this.apps = AvailableAppsService.apps;
     }
 
-    selectedIndexChange(index: number) {
-        this.selectedIndex = index;
-    }
-
-    appOpened(appOpen: boolean) {
-        this.appOpen = appOpen;
-    }
-
-    appClosed() {
-        this.appOpen = false;
-        this.currentlySelectedApp = '';
-    }
-
-    selectApp(appId: string) {
-        this.currentlySelectedApp = appId;
+    selectApp(appLink: string) {
+        this.router.navigate(['apps', appLink]);
     }
 
 
diff --git a/ui/src/app/app-overview/app-overview.module.ts b/ui/src/app/app-overview/app-overview.module.ts
index 1d95617..d924dfd 100644
--- a/ui/src/app/app-overview/app-overview.module.ts
+++ b/ui/src/app/app-overview/app-overview.module.ts
@@ -27,22 +27,39 @@
 import { MatInputModule } from '@angular/material/input';
 import { AppAssetMonitoringModule } from '../app-asset-monitoring/app-asset-monitoring.module';
 import { AppOverviewComponent } from './app-overview.component';
+import { RouterModule } from '@angular/router';
+import { AvailableAppsService } from './apps';
+import { PageName } from '../_enums/page-name.enum';
+import { SharedUiModule } from '@streampipes/shared-ui';
 
 @NgModule({
-    imports: [
-        CommonModule,
-        FlexLayoutModule,
-        CustomMaterialModule,
-        MatGridListModule,
-        MatInputModule,
-        MatFormFieldModule,
-        FormsModule,
-        AppAssetMonitoringModule,
-    ],
-    declarations: [
-        AppOverviewComponent,
-    ],
-    providers: []
+  imports: [
+    AppAssetMonitoringModule,
+    CommonModule,
+    CustomMaterialModule,
+    FlexLayoutModule,
+    FormsModule,
+    MatGridListModule,
+    MatInputModule,
+    MatFormFieldModule,
+    SharedUiModule,
+    RouterModule.forChild([
+      {
+        path: 'apps',
+        children: [{'path': '', component: AppOverviewComponent}, ...AvailableAppsService.apps.map(app => {
+          return {
+            path: app.appLink,
+            data: {authPageNames: [PageName.APPS]},
+            loadChildren: app.appModuleLink
+          };
+        }) as any]
+      }
+    ])
+  ],
+  declarations: [
+    AppOverviewComponent,
+  ],
+  providers: []
 })
 export class AppOverviewModule {
 }
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/app-overview/apps.model.ts
similarity index 85%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/app-overview/apps.model.ts
index 58ba04b..8d1d871 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/app-overview/apps.model.ts
@@ -16,3 +16,10 @@
  *
  */
 
+export interface App {
+  appName: string;
+  appDescription: string;
+  appId: string;
+  appLink: string;
+  appModuleLink?: any;
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/app-overview/apps.routes.ts
similarity index 78%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/app-overview/apps.routes.ts
index 58ba04b..27f672d 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/app-overview/apps.routes.ts
@@ -16,3 +16,10 @@
  *
  */
 
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+
+export class SpAppRoutes {
+
+  static APP_BASE_LINK = 'apps';
+  static BASE: SpBreadcrumbItem = {label: 'Apps', link: [SpAppRoutes.APP_BASE_LINK]};
+}
diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html
index 83e668e..fb59095 100644
--- a/ui/src/app/app.component.html
+++ b/ui/src/app/app.component.html
@@ -15,7 +15,7 @@
   ~ limitations under the License.
   ~
   -->
-<ngx-loading-bar [color]="'rgb(27, 20, 100)'"></ngx-loading-bar>
+<ngx-loading-bar [color]="'var(--color-loading-bar)'"></ngx-loading-bar>
 <div [@routeAnimations]="prepareRoute(outlet)">
     <router-outlet #outlet="outlet"></router-outlet>
-</div>
\ No newline at end of file
+</div>
diff --git a/ui/src/app/assets/assets.module.ts b/ui/src/app/assets/assets.module.ts
new file mode 100644
index 0000000..89d9314
--- /dev/null
+++ b/ui/src/app/assets/assets.module.ts
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { NgModule } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { MatCheckboxModule } from '@angular/material/checkbox';
+import { MatGridListModule } from '@angular/material/grid-list';
+import { MatIconModule } from '@angular/material/icon';
+import { MatInputModule } from '@angular/material/input';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
+import { DragDropModule } from '@angular/cdk/drag-drop';
+import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+import { CoreUiModule } from '../core-ui/core-ui.module';
+import { MatDividerModule } from '@angular/material/divider';
+import { PlatformServicesModule } from '@streampipes/platform-services';
+import { RouterModule } from '@angular/router';
+import { SharedUiModule } from '@streampipes/shared-ui';
+import { SpAssetOverviewComponent } from './components/asset-overview/asset-overview.component';
+import { AssetUploadDialogComponent } from './dialog/asset-upload/asset-upload-dialog.component';
+import { SpAssetDetailsComponent } from './components/asset-details/asset-details.component';
+import { SpAssetSelectionPanelComponent } from './components/asset-details/asset-selection-panel/asset-selection-panel.component';
+import { SpAssetDetailsPanelComponent } from './components/asset-details/asset-details-panel/asset-details-panel.component';
+import { MatTreeModule } from '@angular/material/tree';
+import { SpAssetLinkItemComponent } from './components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component';
+import { EditAssetLinkDialogComponent } from './dialog/edit-asset-link/edit-asset-link-dialog.component';
+import { SpCreateAssetDialogComponent } from './dialog/create-asset/create-asset-dialog.component';
+import { SpManageAssetLinksDialogComponent } from './dialog/manage-asset-links/manage-asset-links-dialog.component';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    CustomMaterialModule,
+    FlexLayoutModule,
+    MatGridListModule,
+    MatButtonModule,
+    MatProgressSpinnerModule,
+    MatIconModule,
+    MatInputModule,
+    MatCheckboxModule,
+    MatDividerModule,
+    MatTooltipModule,
+    FormsModule,
+    DragDropModule,
+    CoreUiModule,
+    ReactiveFormsModule,
+    PlatformServicesModule,
+    RouterModule.forChild([
+      {
+        path: 'assets',
+        children: [
+          {
+            path: '',
+            redirectTo: 'overview',
+            pathMatch: 'full'
+          },
+          {
+            path: 'overview',
+            component: SpAssetOverviewComponent
+          },
+          {
+            path: 'details/:assetId',
+            component: SpAssetDetailsComponent
+          }
+        ]
+      }
+    ]),
+    SharedUiModule,
+    MatTreeModule,
+  ],
+  declarations: [
+    AssetUploadDialogComponent,
+    EditAssetLinkDialogComponent,
+    SpAssetDetailsComponent,
+    SpAssetDetailsPanelComponent,
+    SpAssetLinkItemComponent,
+    SpAssetOverviewComponent,
+    SpAssetSelectionPanelComponent,
+    SpCreateAssetDialogComponent,
+    SpManageAssetLinksDialogComponent
+  ],
+  providers: [],
+})
+export class AssetsModule {}
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/assets/assets.routes.ts
similarity index 75%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/src/app/assets/assets.routes.ts
index a375af7..bacff60 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/assets/assets.routes.ts
@@ -16,7 +16,11 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
-}
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
 
+export class SpAssetRoutes {
+
+  static BASE: SpBreadcrumbItem = {label: 'Asset Management', link: ['assets']};
+  static CREATE: SpBreadcrumbItem = {label: 'New Asset', link: ['assets', 'create']};
+
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.html b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.html
new file mode 100644
index 0000000..a3cc3d1
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.html
@@ -0,0 +1,59 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column" class="page-container-padding-inner" *ngIf="asset">
+    <sp-basic-header-title-component [title]="asset.assetName"></sp-basic-header-title-component>
+
+    <sp-basic-inner-panel panelTitle="Basics" outerMargin="20px 0px">
+        <div fxLayout="column" fxFlex="100">
+            <mat-form-field color="accent">
+                <mat-label>Name</mat-label>
+                <input matInput [(ngModel)]="asset.assetName" [disabled]="!editMode">
+            </mat-form-field>
+            <mat-form-field color="accent">
+                <mat-label>Description</mat-label>
+                <input matInput [(ngModel)]="asset.assetDescription" [disabled]="!editMode">
+            </mat-form-field>
+            <mat-form-field color="accent">
+                <mat-label>ID</mat-label>
+                <input matInput [(ngModel)]="asset.assetId" [disabled]="!editMode">
+            </mat-form-field>
+        </div>
+    </sp-basic-inner-panel>
+
+
+    <sp-basic-inner-panel panelTitle="Linked Resources" outerMargin="0px 0px">
+        <div header fxLayoutAlign="end center" fxLayout="row" fxFlex="100">
+            <button mat-button color="accent" *ngIf="editMode" (click)="openManageAssetLinksDialog()"><i class="material-icons">add</i><span>&nbsp;Manage links</span></button>
+            <button mat-button color="accent" *ngIf="editMode" (click)="openCreateAssetLinkDialog()"><i class="material-icons">add</i><span>&nbsp;Add link</span></button>
+        </div>
+        <div fxLayout="column" fxFlex="100" *ngIf="assetLinkTypes">
+            <div fxLayout="column" *ngFor="let link of asset.assetLinks; let i = index">
+                <sp-asset-link-item-component [assetLink]="link"
+                                              [assetLinkIndex]="i"
+                                              [assetLinkTypes]="assetLinkTypes"
+                                              [editMode]="editMode"
+                                              (openEditAssetLinkEmitter)="openEditAssetLinkDialog($event.assetLink, $event.index, false)"
+                                              (deleteAssetLinkEmitter)="deleteAssetLink($event)"
+                                              class="asset-link-item">
+                </sp-asset-link-item-component>
+
+            </div>
+        </div>
+    </sp-basic-inner-panel>
+</div>
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
similarity index 79%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
index a375af7..1dba0de 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
@@ -16,7 +16,15 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
+.asset-link-item:nth-child(odd) {
+  background: var(--color-bg-1);
 }
 
+.asset-link-item:nth-child(even) {
+  background: var(--color-bg-1);
+}
+
+.asset-link-item {
+  border-bottom: 1px solid var(--color-bg-3);
+  padding: 10px;
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.ts b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.ts
new file mode 100644
index 0000000..9bb9755
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.ts
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { AssetLink, AssetLinkType, GenericStorageService, SpAsset } from '@streampipes/platform-services';
+import { AssetConstants } from '../../../constants/asset.constants';
+import { AssetUploadDialogComponent } from '../../../dialog/asset-upload/asset-upload-dialog.component';
+import { DialogService, PanelType } from '../../../../../../dist/streampipes/shared-ui';
+import { EditAssetLinkDialogComponent } from '../../../dialog/edit-asset-link/edit-asset-link-dialog.component';
+import { SpManageAssetLinksDialogComponent } from '../../../dialog/manage-asset-links/manage-asset-links-dialog.component';
+
+
+@Component({
+  selector: 'sp-asset-details-panel-component',
+  templateUrl: './asset-details-panel.component.html',
+  styleUrls: ['./asset-details-panel.component.scss']
+})
+export class SpAssetDetailsPanelComponent implements OnInit {
+
+  @Input()
+  asset: SpAsset;
+
+  @Input()
+  editMode: boolean;
+
+  @Output()
+  updateAssetEmitter: EventEmitter<SpAsset> = new EventEmitter<SpAsset>();
+
+  assetLinkTypes: AssetLinkType[];
+
+  constructor(private genericStorageService: GenericStorageService,
+              private dialogService: DialogService) {
+
+  }
+
+  ngOnInit(): void {
+    this.genericStorageService.getAllDocuments(AssetConstants.ASSET_LINK_TYPES_DOC_NAME).subscribe(assetLinkTypes => {
+      this.assetLinkTypes = assetLinkTypes.sort((a, b) => a.linkLabel.localeCompare(b.linkLabel));
+    });
+  }
+
+  openManageAssetLinksDialog(): void {
+    const dialogRef = this.dialogService.open(SpManageAssetLinksDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Manage asset links',
+      width: '50vw',
+      data: {
+        'assetLinks': this.asset.assetLinks,
+        'assetLinkTypes': this.assetLinkTypes
+      }
+    });
+
+    dialogRef.afterClosed().subscribe(assetLinks => {
+      if (assetLinks) {
+        this.asset.assetLinks = assetLinks;
+      }
+    });
+  }
+
+  openEditAssetLinkDialog(assetLink: AssetLink, index: number, createMode: boolean): void {
+    const dialogRef = this.dialogService.open(EditAssetLinkDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: createMode ? 'Create ' : 'Update ' + 'asset model',
+      width: '50vw',
+      data: {
+        'assetLink': assetLink,
+        'assetLinkTypes': this.assetLinkTypes,
+        'createMode': createMode
+      }
+    });
+
+    dialogRef.afterClosed().subscribe(storedLink => {
+      if (storedLink) {
+        if (index > -1) {
+          this.asset.assetLinks[index] = storedLink;
+        } else {
+          this.asset.assetLinks.push(storedLink);
+        }
+        this.updateAssetEmitter.emit(this.asset);
+      }
+    });
+  }
+
+  openCreateAssetLinkDialog(): void {
+    const assetLink: AssetLink = {
+      linkLabel: '',
+      linkType: 'data-view',
+      editingDisabled: false,
+      resourceId: '',
+      navigationActive: true,
+      queryHint: 'data-view'
+    };
+    this.openEditAssetLinkDialog(assetLink, -1, true);
+  }
+
+  deleteAssetLink(index: number): void {
+    this.asset.assetLinks.splice(index, 1);
+    this.updateAssetEmitter.emit(this.asset);
+  }
+
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.html b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.html
new file mode 100644
index 0000000..c9c645a
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.html
@@ -0,0 +1,37 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column">
+    <div fxLayout="row" fxLayoutGap="10px">
+        <div fxLayoutAlign="center center">
+            <div fxLayoutAlign="center center" class="link-icon" [ngStyle]="{'background': currentAssetLinkType.linkColor}">
+            <i class="material-icons">{{currentAssetLinkType.linkIcon}}</i>
+            </div>
+        </div>
+        <div fxLayoutAlign="start center"><span class="link-label">{{assetLink.linkLabel}}</span></div>
+        <div fxFlex></div>
+        <div fxLayoutAlign="end center">
+            <button mat-button mat-icon-button color="accent" (click)="openLink()" *ngIf="assetLink.navigationActive"><i class="material-icons">link</i>
+            </button>
+            <button mat-button mat-icon-button color="accent" (click)="editLink()" *ngIf="editMode"><i
+                    class="material-icons">edit</i></button>
+            <button mat-button mat-icon-button color="accent" (click)="deleteLink()" *ngIf="editMode"><i
+                    class="material-icons">delete</i></button>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.scss
similarity index 73%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.scss
index a375af7..11c71ec 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.scss
@@ -16,7 +16,22 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
+.link-type {
+  background: var(--color-primary);
+  padding: 5px;
+  border-radius: 5px;
 }
 
+.link-label {
+  margin-right: 15px;
+  font-weight: 500;
+}
+
+.link-icon {
+  border-radius: 50%;
+  width: 40px;
+  height: 40px;
+  padding: 5px;
+  color: var(--color-bg-1);
+  background: var(--color-bg-3);
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.ts b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.ts
new file mode 100644
index 0000000..49dd4fd
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.ts
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { AssetLink, AssetLinkType } from '@streampipes/platform-services';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'sp-asset-link-item-component',
+  templateUrl: './asset-link-item.component.html',
+  styleUrls: ['./asset-link-item.component.scss']
+})
+export class SpAssetLinkItemComponent implements OnInit {
+
+  @Input()
+  assetLink: AssetLink;
+
+  @Input()
+  assetLinkIndex: number;
+
+  @Input()
+  assetLinkTypes: AssetLinkType[];
+
+  @Input()
+  editMode: boolean;
+
+  @Output()
+  openEditAssetLinkEmitter: EventEmitter<{assetLink: AssetLink, index: number}> = new EventEmitter<{assetLink: AssetLink, index: number}>();
+
+  @Output()
+  deleteAssetLinkEmitter: EventEmitter<number> = new EventEmitter<number>();
+
+  currentAssetLinkType: AssetLinkType;
+
+  constructor(private router: Router) {
+
+  }
+
+  ngOnInit(): void {
+    this.currentAssetLinkType = this.assetLinkTypes.find(t => t.linkType === this.assetLink.linkType);
+  }
+
+  openLink(): void {
+    this.router.navigate([...this.currentAssetLinkType.navPaths, this.assetLink.resourceId]);
+  }
+
+  editLink(): void {
+    this.openEditAssetLinkEmitter.emit({assetLink: this.assetLink, index: this.assetLinkIndex});
+  }
+
+  deleteLink(): void {
+    this.deleteAssetLinkEmitter.emit(this.assetLinkIndex);
+  }
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-details.component.html b/ui/src/app/assets/components/asset-details/asset-details.component.html
new file mode 100644
index 0000000..ceec6c5
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details.component.html
@@ -0,0 +1,61 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<sp-basic-view [showBackLink]="true"
+               [backLinkTarget]="['assets']"
+               [padding]="false">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <div fxLayout="row" fxLayoutAlign="start center" *ngIf="editMode">
+            <button mat-button mat-raised-button color="accent" (click)="saveAsset()">
+                <i class="material-icons">save</i><span>&nbsp;Save</span>
+            </button>
+        </div>
+        <div fxFlex fxLayout="row" fxLayoutAlign="end center">
+
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="column" *ngIf="asset">
+        <mat-drawer-container class="designer-panel-container h-100 dashboard-grid">
+            <mat-drawer #designerDrawer
+                        [opened]="true"
+                        mode="side"
+                        position="start"
+                        class="designer-panel">
+                <div fxLayout="column" fxFlex="100">
+                    <sp-asset-selection-panel-component
+                            [editMode]="editMode"
+                            [assetModel]="asset"
+                            [selectedAsset]="selectedAsset"
+                            (selectedAssetEmitter)="selectedAsset = $event">
+                    </sp-asset-selection-panel-component>
+                </div>
+            </mat-drawer>
+            <mat-drawer-content class="h-100 dashboard-grid">
+                <sp-asset-details-panel-component
+                        *ngIf="selectedAsset"
+                        [asset]="selectedAsset"
+                        [editMode]="editMode"
+                        (updateAssetEmitter)="updateAsset()"
+                        fxFlex="100"
+                        fxLayout="row">
+
+                </sp-asset-details-panel-component>
+            </mat-drawer-content>
+        </mat-drawer-container>
+    </div>
+</sp-basic-view>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/assets/components/asset-details/asset-details.component.scss
similarity index 81%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/assets/components/asset-details/asset-details.component.scss
index 58ba04b..676e7ab 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/assets/components/asset-details/asset-details.component.scss
@@ -16,3 +16,17 @@
  *
  */
 
+.dashboard-grid {
+  display:flex;
+  flex-direction: column;
+  flex: 1 1 100%;
+}
+
+.designer-panel-container {
+  width: 100%;
+  height: 100%;
+}
+
+.designer-panel {
+  width: 400px;
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-details.component.ts b/ui/src/app/assets/components/asset-details/asset-details.component.ts
new file mode 100644
index 0000000..8f3750c
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details.component.ts
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { ActivatedRoute } from '@angular/router';
+import { AssetConstants } from '../../constants/asset.constants';
+import { GenericStorageService, SpAsset, SpAssetModel } from '@streampipes/platform-services';
+import { SpAssetRoutes } from '../../assets.routes';
+
+@Component({
+  selector: 'sp-asset-details-component',
+  templateUrl: './asset-details.component.html',
+  styleUrls: ['./asset-details.component.scss']
+})
+export class SpAssetDetailsComponent implements OnInit {
+
+  asset: SpAssetModel;
+
+  selectedAsset: SpAsset;
+
+  editMode: boolean;
+
+  assetModelId: string;
+
+  constructor(private breadcrumbService: SpBreadcrumbService,
+              private genericStorageService: GenericStorageService,
+              private route: ActivatedRoute) {
+
+  }
+
+  ngOnInit(): void {
+    this.assetModelId = this.route.snapshot.params.assetId;
+    this.editMode = this.route.snapshot.queryParams.editMode;
+    this.loadAsset();
+  }
+
+  loadAsset(): void {
+    this.genericStorageService.getDocument(AssetConstants.ASSET_APP_DOC_NAME, this.assetModelId).subscribe(asset => {
+      this.asset = asset;
+      if (!this.selectedAsset) {
+        this.selectedAsset = this.asset;
+      }
+      this.breadcrumbService.updateBreadcrumb([SpAssetRoutes.BASE, {label: this.asset.assetName}]);
+    });
+  }
+
+  updateAsset() {
+    this.updateSelected();
+  }
+
+  saveAsset() {
+    this.genericStorageService.updateDocument(AssetConstants.ASSET_APP_DOC_NAME, this.asset).subscribe(res => {
+      this.loadAsset();
+      this.editMode = false;
+    });
+  }
+
+  updateSelected() {
+    if (this.asset.assetId === this.selectedAsset.assetId) {
+      this.asset = this.selectedAsset as SpAssetModel;
+    } else {
+      this.asset.assets.forEach(a => {
+        this.walk(a, this.selectedAsset);
+      });
+    }
+  }
+
+  walk(asset: SpAsset, selectedAsset: SpAsset) {
+    if (asset.assetId === selectedAsset.assetId) {
+      asset = selectedAsset;
+    } else {
+      if (asset.assets) {
+        asset.assets.forEach(a => {
+          this.walk(a, selectedAsset);
+        });
+      }
+    }
+  }
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.html b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.html
new file mode 100644
index 0000000..5622b58
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.html
@@ -0,0 +1,76 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column" class="designer-panel-content" *ngIf="assetModel">
+    <div fxLayout="row" class="sp-tab-bg designer-panel-header">
+        <div fxLayoutAlign="start center" class="designer-panel-title"><h4>Asset Browser</h4></div>
+        <div fxFlex fxLayoutAlign="end end">
+
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="column">
+        <div fxFlex fxLayout="column" class="designer-panel-config">
+            <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="sp-tree" #tree>
+                <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
+                    <div [ngClass]="node.assetId === selectedAsset.assetId ? 'asset-node selected-node' : 'asset-node'"
+                         fxLayout="row" fxFlex="100" (click)="selectNode(node)" >
+                        <span fxLayoutAlign="end center">{{node.assetName}}</span>
+                        <div fxLayoutAlign="end center" fxFlex *ngIf="editMode">
+                            <button mat-button
+                                    mat-icon-button
+                                    (click)="addAsset(node)"
+                                    color="accent">
+                                <i class="material-icons">add</i></button>
+                            <button mat-button
+                                    mat-icon-button
+                                    (click)="deleteAsset(node)"
+                                    color="accent">
+                                <i class="material-icons">delete</i></button>
+                        </div>
+                    </div>
+                </mat-tree-node>
+                <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
+                    <div class="mat-tree-node">
+                        <button mat-icon-button matTreeNodeToggle
+                                [attr.data-cy]="'button-' +node.nodeName"
+                                [attr.aria-label]="'Toggle ' + node.nodeName">
+                            <mat-icon class="mat-icon-rtl-mirror">
+                                {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
+                            </mat-icon>
+                        </button>
+                        <div [ngClass]="node.assetId === selectedAsset.assetId ? 'asset-node selected-node' : 'asset-node'"
+                             fxLayout="row" fxFlex="100" (click)="selectNode(node)" >
+                            <span fxLayoutAlign="start center">{{node.assetName}}</span>
+                            <div fxLayoutAlign="end center" fxFlex *ngIf="editMode">
+                                <button mat-button
+                                        mat-icon-button
+                                        (click)="addAsset(node)"
+                                        color="accent">
+                                    <i class="material-icons">add</i></button>
+                            </div>
+                        </div>
+                    </div>
+                    <div [class.sp-tree-invisible]="!treeControl.isExpanded(node)"
+                         role="group">
+                        <ng-container matTreeNodeOutlet></ng-container>
+                    </div>
+                </mat-nested-tree-node>
+            </mat-tree>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
new file mode 100644
index 0000000..2f3b831
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+.designer-panel-content {
+  padding: 0;
+  overflow-y: auto;
+}
+
+.designer-panel-config {
+  padding: 0;
+}
+
+.designer-panel-title {
+  margin-left: 5px;
+}
+
+.designer-panel-header {
+  border-bottom:1px solid var(--color-tab-border);
+}
+
+.sp-tree-invisible {
+  display: none;
+}
+
+.sp-tree ul,
+.sp-tree li {
+  margin-top: 0;
+  margin-bottom: 0;
+  list-style-type: none;
+}
+
+.sp-tree .mat-nested-tree-node div[role=group] {
+  padding-left: 20px;
+}
+
+.sp-tree div[role=group] > .mat-tree-node {
+  padding-left: 20px;
+}
+
+.asset-node {
+  font-weight: normal;
+  cursor: pointer;
+  font-size: 13pt;
+  width: 100%;
+  margin-right: 10px;
+  padding-left: 5px;
+  height: 50px;
+}
+
+.selected-node {
+  font-weight: bold;
+  background: var(--color-bg-2);
+  border-bottom: 2px solid var(--color-primary);
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.ts b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.ts
new file mode 100644
index 0000000..4bf1f1d
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.ts
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
+import { SpAsset, SpAssetModel } from '@streampipes/platform-services';
+import { NestedTreeControl } from '@angular/cdk/tree';
+import { MatTreeNestedDataSource } from '@angular/material/tree';
+
+@Component({
+  selector: 'sp-asset-selection-panel-component',
+  templateUrl: './asset-selection-panel.component.html',
+  styleUrls: ['./asset-selection-panel.component.scss']
+})
+export class SpAssetSelectionPanelComponent implements OnInit {
+
+  @Input()
+  assetModel: SpAssetModel;
+
+  @Input()
+  selectedAsset: SpAsset;
+
+  @Input()
+  editMode: boolean;
+
+  @Output()
+  selectedAssetEmitter: EventEmitter<SpAsset> = new EventEmitter<SpAsset>();
+
+  treeControl = new NestedTreeControl<SpAsset>(node => node.assets);
+  dataSource = new MatTreeNestedDataSource<SpAsset>();
+
+  @ViewChild('tree') tree;
+
+  hasChild = (_: number, node: SpAsset) => !!node.assets && node.assets.length > 0;
+
+  ngOnInit(): void {
+    this.treeControl = new NestedTreeControl<SpAsset>(node => node.assets);
+    this.dataSource = new MatTreeNestedDataSource<SpAsset>();
+    this.dataSource.data = [this.assetModel];
+    this.treeControl.dataNodes = [this.assetModel];
+    this.treeControl.expandAll();
+  }
+
+  selectNode(asset: SpAsset) {
+    this.selectedAssetEmitter.emit(asset);
+  }
+
+  addAsset(node: SpAsset) {
+    if (!node.assets) {
+      node.assets = [];
+    }
+    node.assets.push(this.makeNewAsset());
+    this.dataSource.data = [this.assetModel];
+    this.treeControl.dataNodes = [this.assetModel];
+    this.rerenderTree();
+  }
+
+  deleteAsset(node: SpAsset) {
+    this.removeAssetWithId(this.assetModel.assets, node.assetId);
+    this.rerenderTree();
+  }
+
+  removeAssetWithId(assets: SpAsset[], id: string) {
+    for (let i = 0; i < assets.length; i++) {
+      if (assets[i].assetId === id) {
+        assets.splice(i, 1);
+        return;
+      }
+      if (assets[i].assets) {
+        this.removeAssetWithId(assets[i].assets, id);
+      }
+    }
+  }
+
+  rerenderTree(): void {
+    this.dataSource.data = null;
+    this.dataSource.data = [this.assetModel];
+    this.treeControl.expandAll();
+
+
+  }
+
+  makeNewAsset(): SpAsset {
+    return {assetId: this.makeAssetId(), assetName: 'New Asset', assetDescription: '', assetLinks: [], assetType: undefined, assets: []};
+  }
+
+  makeAssetId(): string {
+    return 'a' + Math.random().toString(36).substring(2, 9);
+  }
+}
diff --git a/ui/src/app/assets/components/asset-overview/asset-overview.component.html b/ui/src/app/assets/components/asset-overview/asset-overview.component.html
new file mode 100644
index 0000000..9fcac02
--- /dev/null
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.html
@@ -0,0 +1,119 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<sp-basic-view [showBackLink]="false" [padding]="true">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                data-cy="connect-create-new-adapter-button"
+                (click)="createNewAsset()">
+            <i class="material-icons">add</i>&nbsp;New asset
+        </button>
+        <div fxFlex fxLayout="row" fxLayoutAlign="end center">
+            <button mat-button mat-icon-button matTooltip="Refresh assets" matTooltipPosition="below" color="accent"
+                    (click)="loadAssets()">
+                <i class="material-icons">
+                    refresh
+                </i>
+            </button>
+            <button mat-button mat-icon-button matTooltip="Upload assets" matTooltipPosition="below" color="accent"
+                    (click)="uploadAsset()">
+                <i class="material-icons">
+                    cloud_upload
+                </i>
+            </button>
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="column">
+        <sp-basic-header-title-component title="My assets"></sp-basic-header-title-component>
+        <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+            <sp-basic-inner-panel [showTitle]="false" innerPadding="0" outerMargin="0" fxFlex="90" [hideToolbar]="true">
+                <div fxFlex="100" fxLayout="column" *ngIf="existingAssets.length > 0">
+                    <div fxFlex="100" fxLayout="column">
+                        <table fxFlex="100" mat-table [dataSource]="dataSource" style="width: 100%;" matSort>
+
+                            <ng-container matColumnDef="name">
+                                <th mat-header-cell mat-sort-header *matHeaderCellDef> Name</th>
+                                <td mat-cell *matCellDef="let asset">
+                                    <div fxLayout="row" fxLayoutAlign="start center">
+                                        <div fxLayoutAlign="start center">
+                                            <i class="material-icons">precision_manufacturing</i>
+                                        </div>
+                                        <div fxLayoutAlign="center start" fxLayout="column" class="ml-10">
+                                            <h4 style="margin-bottom:0px;">{{asset.assetName}}</h4>
+                                            <h5>{{asset.assetDescription != '' ? asset.assetDescription : '-'}}</h5>
+                                        </div>
+                                    </div>
+
+                                </td>
+                            </ng-container>
+                            <ng-container matColumnDef="action">
+                                <th mat-header-cell *matHeaderCellDef style="justify-content: center;"> Actions</th>
+                                <td mat-cell *matCellDef="let asset">
+                                    <div fxLayout="row">
+                            <span fxFlex fxFlexOrder="1" fxLayout="row" fxLayoutAlign="center center">
+                                <button color="accent" mat-button mat-icon-button matTooltip="Show info"
+                                        matTooltipPosition="above" (click)="goToDetailsView(asset)"><i
+                                        class="material-icons">search</i>
+                                </button>
+                            </span>
+                            <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center">
+                                <button color="accent" mat-button mat-icon-button matTooltip="Edit asset"
+                                        matTooltipPosition="above" (click)="goToDetailsView(asset, true)"><i
+                                        class="material-icons">edit</i>
+                                </button>
+                            </span>
+                                        <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center">
+<!--                    <button color="accent" mat-button mat-icon-button matTooltip="Manage permissions"-->
+                                            <!--                            matTooltipPosition="above" (click)="showPermissionsDialog(adapter)"><i-->
+                                            <!--                            class="material-icons">share</i>-->
+                                            <!--                    </button>-->
+                </span>
+                                        <span fxFlex fxFlexOrder="4" fxLayout="row" fxLayoutAlign="center center">
+                    <button color="accent" mat-button mat-icon-button matTooltip="Delete adapter"
+                            data-cy="delete" matTooltipPosition="above" (click)="deleteAsset(asset)">
+                        <i class="material-icons">delete</i>
+                    </button>
+                </span>
+                                    </div>
+                                </td>
+                            </ng-container>
+
+                            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                            <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+
+                        </table>
+                    </div>
+                    <div fxFlex="100" fxLayoutAlign="end end">
+                        <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"
+                                       [pageSize]="20"
+                                       color="accent">
+                        </mat-paginator>
+                    </div>
+                </div>
+                <div fxFlex="100"
+                     fxLayout="column"
+                     fxLayoutAlign="center center"
+                     *ngIf="existingAssets.length == 0">
+                    <h5>(no assets available)</h5>
+                </div>
+            </sp-basic-inner-panel>
+        </div>
+    </div>
+</sp-basic-view>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/assets/components/asset-overview/asset-overview.component.scss
similarity index 95%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/assets/components/asset-overview/asset-overview.component.scss
index 58ba04b..d172895 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.scss
@@ -16,3 +16,6 @@
  *
  */
 
+.ml-10 {
+  margin-left: 10px;
+}
diff --git a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
new file mode 100644
index 0000000..1800e33
--- /dev/null
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { MatTableDataSource } from '@angular/material/table';
+import { GenericStorageService, SpAssetModel } from '@streampipes/platform-services';
+import { AssetConstants } from '../../constants/asset.constants';
+import { DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpAssetRoutes } from '../../assets.routes';
+import { AssetUploadDialogComponent } from '../../dialog/asset-upload/asset-upload-dialog.component';
+import { Router } from '@angular/router';
+import { SpCreateAssetDialogComponent } from '../../dialog/create-asset/create-asset-dialog.component';
+
+@Component({
+  selector: 'sp-asset-overview-component',
+  templateUrl: './asset-overview.component.html',
+  styleUrls: ['./asset-overview.component.scss']
+})
+export class SpAssetOverviewComponent implements OnInit {
+
+  existingAssets: SpAssetModel[] = [];
+
+  displayedColumns: string[] = ['name', 'action'];
+
+  dataSource: MatTableDataSource<SpAssetModel>;
+
+  constructor(private genericStorageService: GenericStorageService,
+              private breadcrumbService: SpBreadcrumbService,
+              private dialogService: DialogService,
+              private router: Router) {
+
+  }
+
+  ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpAssetRoutes.BASE));
+    this.loadAssets();
+  }
+
+  loadAssets(): void {
+    this.genericStorageService.getAllDocuments(AssetConstants.ASSET_APP_DOC_NAME).subscribe(result => {
+      this.existingAssets = result as SpAssetModel[];
+      this.dataSource = new MatTableDataSource<SpAssetModel>(this.existingAssets);
+    });
+  }
+
+  createNewAsset(assetModel?: SpAssetModel) {
+    if (!assetModel) {
+      assetModel = {
+        assetName: 'New Asset',
+        assetDescription: '',
+        assetLinks: [],
+        assetId: this.generateId(6),
+        _id: this.generateId(24),
+        appDocType: 'asset-management',
+        removable: true,
+        _rev: undefined,
+        assets: [],
+        assetType: undefined
+      };
+    }
+    const dialogRef = this.dialogService.open(SpCreateAssetDialogComponent, {
+      panelType: PanelType.STANDARD_PANEL,
+      title: 'Create asset',
+      width: '40vw',
+      data: {
+        'createMode': true,
+        'assetModel': assetModel
+      }
+    });
+
+    dialogRef.afterClosed().subscribe(() => {
+      this.loadAssets();
+    });
+  }
+
+  private generateId(length): string {
+    const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    let result = '';
+    for (let i = length; i > 0; --i) {
+      result += chars[Math.round(Math.random() * (chars.length - 1))];
+    }
+    return result;
+  }
+
+  uploadAsset() {
+    const dialogRef = this.dialogService.open(AssetUploadDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Upload asset model',
+      width: '40vw',
+    });
+
+    dialogRef.afterClosed().subscribe(reload => {
+      if (reload) {
+        this.loadAssets();
+      }
+    });
+  }
+
+  goToDetailsView(asset: SpAssetModel,
+                  editMode = false) {
+    if (!editMode) {
+      this.router.navigate(['assets', 'details', asset._id]);
+    } else {
+      this.router.navigate(['assets', 'details', asset._id], {queryParams: {'editMode': editMode}});
+    }
+  }
+
+  deleteAsset(asset: SpAssetModel) {
+    this.genericStorageService.deleteDocument(
+      AssetConstants.ASSET_APP_DOC_NAME,
+      asset._id,
+      asset._rev)
+      .subscribe(result => {
+        this.loadAssets();
+      });
+  }
+
+
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/assets/constants/asset.constants.ts
similarity index 83%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/assets/constants/asset.constants.ts
index 58ba04b..ee412ee 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/assets/constants/asset.constants.ts
@@ -16,3 +16,8 @@
  *
  */
 
+export class AssetConstants {
+
+  public static ASSET_APP_DOC_NAME = 'asset-management';
+  public static ASSET_LINK_TYPES_DOC_NAME = 'asset-link-type';
+}
diff --git a/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.html b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.html
new file mode 100644
index 0000000..9cd6bf1
--- /dev/null
+++ b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.html
@@ -0,0 +1,68 @@
+<!--
+~ Licensed to the Apache Software Foundation (ASF) under one or more
+~ contributor license agreements.  See the NOTICE file distributed with
+~ this work for additional information regarding copyright ownership.
+~ The ASF licenses this file to You under the Apache License, Version 2.0
+~ (the "License"); you may not use this file except in compliance with
+~ the License.  You may obtain a copy of the License at
+~
+~    http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+~
+-->
+
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100" fxLayout="column">
+            <div fxFlex style="margin:5px;width:100%" fxLayout="column">
+                <mat-form-field style="width: 95%" (click)="fileInput.click();" color="accent">
+                    <mat-label>Upload JSON file</mat-label>
+                    <input matInput placeholder="File" disabled (value)="fileName">
+                    <input #fileInput type="file" style="display:none;"
+                           (change)="handleFileInput($event.target.files)"
+                           data-cy="sp-file-management-file-input">
+                    <div>
+                        {{fileName}}
+                        <mat-progress-bar mode="determinate" value="{{uploadStatus}}" *ngIf="uploadStatus > 0" color="accent"></mat-progress-bar>
+                    </div>
+                    <button color="accent" matSuffix
+                            mat-button style="min-width: 0px">
+                        <mat-icon *ngIf="uploadStatus < 99">insert_drive_file</mat-icon>
+                        <mat-icon *ngIf="uploadStatus == 100" class="green-icon">check_circle</mat-icon>
+                    </button>
+                    <mat-error *ngIf="!hasInput">
+                        {{errorMessage}}
+                    </mat-error>
+                </mat-form-field>
+            </div>
+            <div fxFlex="100">
+                <mat-form-field style="width: 100%;height: 100%;" color="accent">
+                    <mat-label>Insert model</mat-label>
+                    <textarea matInput [(ngModel)]="jsonModel" style="height: 100%;"
+                              cdkTextareaAutosize
+                              cdkAutosizeMinRows="30"
+                              cdkAutosizeMaxRows="30"></textarea>
+                </mat-form-field>
+            </div>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                [disabled]="jsonModel === undefined"
+                (click)="store()" data-cy="sp-file-management-store-file" style="margin-right:10px;">
+            Create asset
+        </button>
+        <button mat-button mat-raised-button class="mat-basic" (click)="cancel()" style="margin-right:10px;">
+            Cancel
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.scss
similarity index 95%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.scss
index 58ba04b..d25ee74 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.scss
@@ -16,3 +16,4 @@
  *
  */
 
+@import 'src/scss/sp/sp-dialog';
\ No newline at end of file
diff --git a/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.ts b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.ts
new file mode 100644
index 0000000..b1f52f1
--- /dev/null
+++ b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.ts
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { DialogRef } from '@streampipes/shared-ui';
+import { GenericStorageService } from '@streampipes/platform-services';
+import { AssetConstants } from '../../constants/asset.constants';
+
+@Component({
+  selector: 'sp-file-upload-dialog-component',
+  templateUrl: './asset-upload-dialog.component.html',
+  styleUrls: ['./asset-upload-dialog.component.scss']
+})
+export class AssetUploadDialogComponent implements OnInit {
+
+  inputValue: string;
+  fileName: string;
+
+  jsonModel: string;
+
+  hasInput: boolean;
+  errorMessage = 'Please enter a value';
+
+  uploadStatus = 0;
+
+  constructor(private dialogRef: DialogRef<AssetUploadDialogComponent>,
+              private genericStorageService: GenericStorageService) {
+
+  }
+
+  ngOnInit(): void {
+  }
+
+  handleFileInput(files: any) {
+    this.uploadStatus = 0;
+
+    const fr = new FileReader();
+
+    fr.onload = (ev => {
+      const jsonObject = JSON.parse(ev.target.result as string);
+      this.jsonModel = JSON.stringify(jsonObject, null, 2);
+    });
+
+    fr.readAsText(files.item(0));
+  }
+
+  store() {
+    this.uploadStatus = 0;
+    if (this.jsonModel !== undefined) {
+      const jsonObject = JSON.parse(this.jsonModel);
+      jsonObject._rev = undefined;
+      this.genericStorageService.createDocument(AssetConstants.ASSET_APP_DOC_NAME, jsonObject).subscribe(result => {
+        this.dialogRef.close(true);
+      });
+    }
+  }
+
+  cancel() {
+    this.dialogRef.close();
+  }
+
+}
diff --git a/ui/src/app/assets/dialog/base-asset-links.directive.ts b/ui/src/app/assets/dialog/base-asset-links.directive.ts
new file mode 100644
index 0000000..28df15b
--- /dev/null
+++ b/ui/src/app/assets/dialog/base-asset-links.directive.ts
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Directive } from '@angular/core';
+import {
+  AdapterDescriptionUnion, AdapterService,
+  Dashboard, DashboardService,
+  DataLakeMeasure, DatalakeRestService, DataViewDataExplorerService, FileMetadata, FilesService, GenericStorageService,
+  Pipeline, PipelineElementService, PipelineService,
+  SpDataStream
+} from '@streampipes/platform-services';
+import { zip } from 'rxjs';
+
+@Directive()
+export abstract class BaseAssetLinksDirective {
+
+  // Resources
+  pipelines: Pipeline[];
+  dataViews: Dashboard[];
+  dashboards: Dashboard[];
+  dataLakeMeasures: DataLakeMeasure[];
+  dataSources: SpDataStream[];
+  adapters: AdapterDescriptionUnion[];
+  files: FileMetadata[];
+
+  allResources: any[] = [];
+
+  constructor(protected genericStorageService: GenericStorageService,
+              protected pipelineService: PipelineService,
+              protected dataViewService: DataViewDataExplorerService,
+              protected dashboardService: DashboardService,
+              protected dataLakeService: DatalakeRestService,
+              protected pipelineElementService: PipelineElementService,
+              protected adapterService: AdapterService,
+              protected filesService: FilesService) {
+
+  }
+
+  onInit() {
+    this.getAllResources();
+  }
+
+  getAllResources() {
+    zip(
+      this.pipelineService.getOwnPipelines(),
+        this.dataViewService.getDataViews(),
+        this.dashboardService.getDashboards(),
+        this.pipelineElementService.getDataStreams(),
+        this.dataLakeService.getAllMeasurementSeries(),
+        this.filesService.getFileMetadata(),
+        this.adapterService.getAdapters()).subscribe((
+      [pipelines,
+        dataViews,
+        dashboards,
+        streams,
+        measurements,
+        files,
+        adapters
+      ]) => {
+      this.pipelines = pipelines.sort((a, b) => a.name.localeCompare(b.name));
+      this.dataViews = dataViews.sort((a, b) => a.name.localeCompare(b.name));
+      this.dashboards = dashboards.sort((a, b) => a.name.localeCompare(b.name));
+      this.dataSources = streams.sort((a, b) => a.name.localeCompare(b.name));
+      this.dataLakeMeasures = measurements.sort((a, b) => a.measureName.localeCompare(b.measureName));
+      this.files = files.sort((a, b) => a.originalFilename.localeCompare(b.originalFilename));
+      this.adapters = adapters.sort((a, b) => a.name.localeCompare(b.name));
+
+      this.allResources = [
+        ...this.pipelines,
+        ...this.dataViews,
+        ...this.dashboards,
+        ...this.dataSources,
+        ...this.dataLakeMeasures,
+        ...this.files,
+        ...this.adapters
+      ];
+      this.afterResourcesLoaded();
+    });
+  }
+
+  abstract afterResourcesLoaded(): void;
+}
+
diff --git a/ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.html b/ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.html
new file mode 100644
index 0000000..3515fd9
--- /dev/null
+++ b/ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.html
@@ -0,0 +1,50 @@
+<!--
+~ Licensed to the Apache Software Foundation (ASF) under one or more
+~ contributor license agreements.  See the NOTICE file distributed with
+~ this work for additional information regarding copyright ownership.
+~ The ASF licenses this file to You under the Apache License, Version 2.0
+~ (the "License"); you may not use this file except in compliance with
+~ the License.  You may obtain a copy of the License at
+~
+~    http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+~
+-->
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100">
+            <div fxFlex="100" fxLayout="column" style="margin:5px;width:100%">
+                <mat-form-field class="full-width" color="accent">
+                    <mat-label>Asset Name</mat-label>
+                    <input matInput
+                           data-cy="asset-name"
+                           [(ngModel)]="assetModel.assetName">
+                </mat-form-field>
+                <mat-form-field class="full-width" color="accent">
+                    <mat-label>Description</mat-label>
+                    <input matInput [(ngModel)]="assetModel.assetDescription">
+                </mat-form-field>
+            </div>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions actions-align-right">
+        <button mat-button mat-raised-button class="mat-basic mr-10"
+                (click)="onCancel()" style="margin-right: 10px;">
+            Close
+        </button>
+        <button mat-button mat-raised-button color="accent"
+                data-cy="save-data-view"
+                (click)="onSave()">
+            {{createMode ? 'Create' : 'Save'}}
+        </button>
+    </div>
+</div>
+
+
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.scss
similarity index 95%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.scss
index 58ba04b..704f843 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.scss
@@ -16,3 +16,4 @@
  *
  */
 
+@import 'src/scss/sp/sp-dialog';
diff --git a/ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.ts b/ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.ts
new file mode 100644
index 0000000..460a304
--- /dev/null
+++ b/ui/src/app/assets/dialog/create-asset/create-asset-dialog.component.ts
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+import { Component, Input, OnInit } from '@angular/core';
+import { AssetManagementService, DataViewDataExplorerService, SpAssetModel } from '@streampipes/platform-services';
+import { DialogRef } from '@streampipes/shared-ui';
+
+@Component({
+  selector: 'sp-create-asset-dialog-component',
+  templateUrl: './create-asset-dialog.component.html',
+  styleUrls: ['./create-asset-dialog.component.scss']
+})
+export class SpCreateAssetDialogComponent implements OnInit {
+
+  @Input() createMode: boolean;
+  @Input() assetModel: SpAssetModel;
+
+  constructor(
+    private dialogRef: DialogRef<SpCreateAssetDialogComponent>,
+    private assetManagementService: AssetManagementService) {
+  }
+
+  ngOnInit() {
+
+  }
+
+  onCancel(): void {
+    this.dialogRef.close();
+  }
+
+  onSave(): void {
+    if (this.createMode) {
+      this.assetManagementService.createAsset(this.assetModel).subscribe(() => {
+        this.dialogRef.close();
+      });
+    } else {
+      this.assetManagementService.updateAsset(this.assetModel).subscribe(() => {
+        this.dialogRef.close();
+      });
+    }
+  }
+
+}
diff --git a/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.html b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.html
new file mode 100644
index 0000000..143d093
--- /dev/null
+++ b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.html
@@ -0,0 +1,145 @@
+<!--
+~ Licensed to the Apache Software Foundation (ASF) under one or more
+~ contributor license agreements.  See the NOTICE file distributed with
+~ this work for additional information regarding copyright ownership.
+~ The ASF licenses this file to You under the Apache License, Version 2.0
+~ (the "License"); you may not use this file except in compliance with
+~ the License.  You may obtain a copy of the License at
+~
+~    http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+~
+-->
+
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100" fxLayout="column" *ngIf="clonedAssetLink">
+            <div fxLayout="column" class="link-configuration link-type-selection">
+                <mat-form-field color="accent">
+                    <mat-label>Link Type</mat-label>
+                    <mat-select fxFlex [(value)]="selectedLinkType"
+                                required (selectionChange)="onLinkTypeChanged($event)">
+                        <mat-option *ngFor="let assetLinkType of assetLinkTypes"
+                                    [value]="assetLinkType">{{assetLinkType.linkLabel}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType.linkQueryHint === 'pipeline'" fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Pipelines</mat-label>
+                    <mat-select [(ngModel)]="currentResource"
+                                fxFlex (selectionChange)="changeLabel($event.value._id, $event.value.name, $event.value)"
+                                required>
+                        <mat-option *ngFor="let pipeline of pipelines"
+                                    [value]="pipeline">{{pipeline.name}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType.linkQueryHint === 'data-source'" fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Data Source</mat-label>
+                    <mat-select (selectionChange)="changeLabel($event.value.elementId, $event.value.name, $event.value)"
+                                [(value)]="currentResource"
+                                fxFlex
+                                required>
+                        <mat-option *ngFor="let source of dataSources"
+                                    [value]="source">{{source.name}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType.linkQueryHint === 'dashboard'" fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Dashboards</mat-label>
+                    <mat-select (selectionChange)="changeLabel($event.value._id, $event.value.name, $event.value)"
+                                [(value)]="currentResource"
+                                fxFlex
+                                required>
+                        <mat-option *ngFor="let dashboard of dashboards"
+                                    [value]="dashboard">{{dashboard.name}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType.linkQueryHint === 'data-view'" fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Data Views</mat-label>
+                    <mat-select (selectionChange)="changeLabel($event.value._id, $event.value.name, $event.value)"
+                                [(value)]="currentResource"
+                                fxFlex
+                                required>
+                        <mat-option *ngFor="let dataView of dataViews"
+                                    [value]="dataView">{{dataView.name}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType.linkQueryHint === 'adapter'" fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Adapter</mat-label>
+                    <mat-select (selectionChange)="changeLabel($event.value.elementId, $event.value.name, $event.value)"
+                                [(value)]="currentResource"
+                                fxFlex
+                                required>
+                        <mat-option *ngFor="let adapter of adapters"
+                                    [value]="adapter">{{adapter.name}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType.linkQueryHint === 'measurement'" fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Data Lake Storage</mat-label>
+                    <mat-select (selectionChange)="changeLabel($event.value.elementId, $event.value.measureName, $event.value)"
+                                [(value)]="currentResource"
+                                fxFlex
+                                required>
+                        <mat-option *ngFor="let measure of dataLakeMeasures"
+                                    [value]="measure">{{measure.measureName}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType.linkQueryHint === 'file'" fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Files</mat-label>
+                    <mat-select (selectionChange)="changeLabel($event.value.fileId, $event.value.originalFilename, $event.value)"
+                                [(value)]="currentResource"
+                                fxFlex
+                                required>
+                        <mat-option *ngFor="let file of files"
+                                    [value]="file">{{file.originalFilename}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent">
+                    <mat-label>Label</mat-label>
+                    <input matInput [(ngModel)]="clonedAssetLink.linkLabel" required>
+                </mat-form-field>
+            </div>
+            <div fxLayout="column" class="link-configuration">
+                <mat-form-field color="accent">
+                    <mat-label>Resource ID</mat-label>
+                    <input matInput [(ngModel)]="clonedAssetLink.resourceId" required [disabled]="true">
+                </mat-form-field>
+            </div>
+            <div fxFlex="100">
+
+            </div>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                (click)="store()" style="margin-right:10px;" [disabled]="!clonedAssetLink.resourceId">
+            {{createMode ? 'Create ' : 'Update' }} link
+        </button>
+        <button mat-button mat-raised-button class="mat-basic" (click)="cancel()" style="margin-right:10px;">
+            Cancel
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.scss
similarity index 81%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.scss
index a375af7..e1f0e27 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.scss
@@ -16,7 +16,15 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
+@import 'src/scss/sp/sp-dialog';
+
+.link-type-selection {
 }
 
+.link-configuration {
+  padding: 10px;
+  width:100%;
+  margin:5px;
+  background: var(--color-bg-1);
+  border: 1px solid var(--color-bg-3);
+}
diff --git a/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.ts b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.ts
new file mode 100644
index 0000000..417a086
--- /dev/null
+++ b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.ts
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import { DialogRef } from '@streampipes/shared-ui';
+import {
+  AdapterDescriptionUnion,
+  SpDataStream,
+  AdapterService,
+  AssetLink,
+  AssetLinkType,
+  Dashboard,
+  DashboardService,
+  DataLakeMeasure, DatalakeRestService,
+  DataViewDataExplorerService,
+  GenericStorageService,
+  Pipeline,
+  PipelineService,
+  PipelineElementService, FileMetadata, FilesService
+} from '@streampipes/platform-services';
+import { FormGroup } from '@angular/forms';
+import { zip } from 'rxjs';
+import { MatSelectChange } from '@angular/material/select';
+import { BaseAssetLinksDirective } from '../base-asset-links.directive';
+
+@Component({
+  selector: 'sp-edit-asset-link-dialog-component',
+  templateUrl: './edit-asset-link-dialog.component.html',
+  styleUrls: ['./edit-asset-link-dialog.component.scss']
+})
+export class EditAssetLinkDialogComponent extends BaseAssetLinksDirective implements OnInit {
+
+  @Input()
+  assetLink: AssetLink;
+
+  @Input()
+  assetLinkTypes: AssetLinkType[];
+
+  @Input()
+  createMode: boolean;
+
+  parentForm: FormGroup;
+
+  clonedAssetLink: AssetLink;
+
+
+  currentResource: any;
+
+  selectedLinkType: AssetLinkType;
+
+  constructor(private dialogRef: DialogRef<EditAssetLinkDialogComponent>,
+              protected genericStorageService: GenericStorageService,
+              protected pipelineService: PipelineService,
+              protected dataViewService: DataViewDataExplorerService,
+              protected dashboardService: DashboardService,
+              protected dataLakeService: DatalakeRestService,
+              protected pipelineElementService: PipelineElementService,
+              protected adapterService: AdapterService,
+              protected filesService: FilesService) {
+    super(
+      genericStorageService,
+      pipelineService,
+      dataViewService,
+      dashboardService,
+      dataLakeService,
+      pipelineElementService,
+      adapterService,
+      filesService);
+  }
+
+  ngOnInit(): void {
+    super.onInit();
+    this.clonedAssetLink = {...this.assetLink};
+    this.selectedLinkType = this.getCurrAssetLinkType();
+  }
+
+  getCurrAssetLinkType(): AssetLinkType {
+    return this.assetLinkTypes.find(a => a.linkType === this.clonedAssetLink.linkType);
+  }
+
+  store() {
+    this.assetLink = this.clonedAssetLink;
+    this.dialogRef.close(this.assetLink);
+  }
+
+  cancel() {
+    this.dialogRef.close();
+  }
+
+  onLinkTypeChanged(event: MatSelectChange): void {
+    this.selectedLinkType = event.value;
+    const linkType = this.assetLinkTypes.find(a => a.linkType === this.selectedLinkType.linkType);
+    this.clonedAssetLink.editingDisabled = false;
+    this.clonedAssetLink.linkType = linkType.linkType;
+    this.clonedAssetLink.queryHint = linkType.linkQueryHint;
+    this.clonedAssetLink.navigationActive = linkType.navigationActive;
+  }
+
+  changeLabel(id: string, label: string, currentResource: any) {
+    this.clonedAssetLink.resourceId = id;
+    this.clonedAssetLink.linkLabel = label;
+    this.currentResource = currentResource;
+  }
+
+  afterResourcesLoaded(): void {
+    if (!this.createMode) {
+      this.currentResource = this.allResources.find(r => r._id === this.clonedAssetLink.resourceId ||
+        r.elementId === this.clonedAssetLink.resourceId);
+    }
+  }
+
+}
diff --git a/ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.html b/ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.html
new file mode 100644
index 0000000..eba2f81
--- /dev/null
+++ b/ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.html
@@ -0,0 +1,216 @@
+<!--
+~ Licensed to the Apache Software Foundation (ASF) under one or more
+~ contributor license agreements.  See the NOTICE file distributed with
+~ this work for additional information regarding copyright ownership.
+~ The ASF licenses this file to You under the Apache License, Version 2.0
+~ (the "License"); you may not use this file except in compliance with
+~ the License.  You may obtain a copy of the License at
+~
+~    http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+~
+-->
+
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100" fxLayout="column" *ngIf="clonedAssetLinks">
+            <div fxLayout="column" class="link-configuration">
+                <div fxLayout="row" fxLayoutAlign="start center" class="mb-10" fxFlex="100">
+                    <div fxLayout="row" fxLayoutAlign="start center">
+                        <span class="general-options-header mb-0">Adapters</span>
+                    </div>
+                    <div fxLayout="row" fxLayoutAlign="end center" fxFlex>
+                        <button mat-button mat-raised-button color="accent" class="small-button"
+                                (click)="selectAll(adapters, elementIdFunction, nameFunction, 'adapter')"
+                                style="margin-right:5px;margin-left:15px;">
+                            <span>Select All</span>
+                        </button>
+                        <button mat-button mat-raised-button class="mat-basic small-button"
+                                (click)="deselectAll(adapters, elementIdFunction)"
+                                style="margin-right:10px;margin-left:5px;">
+                            <span>Deselect All</span>
+                        </button>
+                    </div>
+                </div>
+                <div *ngFor="let element of adapters" fxLayout="row">
+                    <mat-checkbox color="accent"
+                                  [checked]="linkSelected(element.elementId)"
+                                  (change)="selectLink($event.checked, element.elementId, element.name, 'adapter')">
+                        {{element.name}}
+                    </mat-checkbox>
+                </div>
+            </div>
+            <div fxLayout="column" class="link-configuration">
+                <div fxLayout="row" fxLayoutAlign="start center" class="mb-10">
+                    <div fxLayout="row" fxLayoutAlign="start center">
+                        <span class="general-options-header mb-0">Dasboards</span>
+                    </div>
+                    <div fxLayout="row" fxLayoutAlign="end center" fxFlex>
+                        <button mat-button mat-raised-button color="accent" class="small-button"
+                                (click)="selectAll(dashboards, idFunction, nameFunction, 'dashboard')"
+                                style="margin-right:5px;margin-left:15px;">
+                            <span>Select All</span>
+                        </button>
+                        <button mat-button mat-raised-button class="mat-basic small-button"
+                                (click)="deselectAll(dashboards, idFunction)"
+                                style="margin-right:10px;margin-left:5px;">
+                            <span>Deselect All</span>
+                        </button>
+                    </div>
+                </div>
+                <div *ngFor="let element of dashboards" fxLayout="row">
+                    <mat-checkbox color="accent"
+                                  [checked]="linkSelected(element._id)"
+                                  (change)="selectLink($event.checked, element._id, element.name, 'dashboard')">
+                        {{element.name}}
+                    </mat-checkbox>
+                </div>
+            </div>
+            <div fxLayout="column" class="link-configuration">
+                <div fxLayout="row" fxLayoutAlign="start center" class="mb-10">
+                    <div fxLayout="row" fxLayoutAlign="start center">
+                        <span class="general-options-header mb-0">Data Lake Storage</span>
+                    </div>
+                    <div fxLayout="row" fxLayoutAlign="end center" fxFlex>
+                        <button mat-button mat-raised-button color="accent" class="small-button"
+                                (click)="selectAll(dataLakeMeasures, elementIdFunction, measureNameFunction, 'measurement')"
+                                style="margin-right:5px;margin-left:15px;">
+                            <span>Select All</span>
+                        </button>
+                        <button mat-button mat-raised-button class="mat-basic small-button"
+                                (click)="deselectAll(dataLakeMeasures, elementIdFunction)"
+                                style="margin-right:10px;margin-left:5px;">
+                            <span>Deselect All</span>
+                        </button>
+                    </div>
+                </div>
+                <div *ngFor="let element of dataLakeMeasures" fxLayout="row">
+                    <mat-checkbox color="accent"
+                                  [checked]="linkSelected(element.elementId)"
+                                  (change)="selectLink($event.checked, element.elementId, element.measureName, 'measurement')">
+                        {{element.measureName}}
+                    </mat-checkbox>
+                </div>
+            </div>
+            <div fxLayout="column" class="link-configuration">
+                <div fxLayout="row" fxLayoutAlign="start center" class="mb-10">
+                    <div fxLayout="row" fxLayoutAlign="start center">
+                        <span class="general-options-header mb-0">Data Sources</span>
+                    </div>
+                    <div fxLayout="row" fxLayoutAlign="end center" fxFlex>
+                        <button mat-button mat-raised-button color="accent" class="small-button"
+                                (click)="selectAll(dataSources, elementIdFunction, nameFunction, 'data-source')"
+                                style="margin-right:5px;margin-left:15px;">
+                            <span>Select All</span>
+                        </button>
+                        <button mat-button mat-raised-button class="mat-basic small-button"
+                                (click)="deselectAll(dataSources, elementIdFunction)"
+                                style="margin-right:10px;margin-left:5px;">
+                            <span>Deselect All</span>
+                        </button>
+                    </div>
+                </div>
+                <div *ngFor="let source of dataSources" fxLayout="row">
+                    <mat-checkbox color="accent"
+                                  [checked]="linkSelected(source.elementId)"
+                                  (change)="selectLink($event.checked, source.elementId, source.name, 'data-source')">
+                        {{source.name}}
+                    </mat-checkbox>
+                </div>
+            </div>
+            <div fxLayout="column" class="link-configuration">
+                <div fxLayout="row" fxLayoutAlign="start center" class="mb-10">
+                    <div fxLayout="row" fxLayoutAlign="start center">
+                        <span class="general-options-header mb-0">Data Views</span>
+                    </div>
+                    <div fxLayout="row" fxLayoutAlign="end center" fxFlex>
+                        <button mat-button mat-raised-button color="accent" class="small-button"
+                                (click)="selectAll(dataViews, idFunction, nameFunction, 'data-view')"
+                                style="margin-right:5px;margin-left:15px;">
+                            <span>Select All</span>
+                        </button>
+                        <button mat-button mat-raised-button class="mat-basic small-button"
+                                (click)="deselectAll(dataViews, idFunction)"
+                                style="margin-right:10px;margin-left:5px;">
+                            <span>Deselect All</span>
+                        </button>
+                    </div>
+                </div>
+                <div *ngFor="let element of dataViews" fxLayout="row">
+                    <mat-checkbox color="accent"
+                                  [checked]="linkSelected(element._id)"
+                                  (change)="selectLink($event.checked, element._id, element.name, 'data-view')">
+                        {{element.name}}
+                    </mat-checkbox>
+                </div>
+            </div>
+            <div fxLayout="column" class="link-configuration">
+                <div fxLayout="row" fxLayoutAlign="start center" class="mb-10">
+                    <div fxLayout="row" fxLayoutAlign="start center">
+                        <span class="general-options-header mb-0">Files</span>
+                    </div>
+                    <div fxLayout="row" fxLayoutAlign="end center" fxFlex>
+                        <button mat-button mat-raised-button color="accent" class="small-button"
+                                (click)="selectAll(files, fileIdFunction, filenameFunction, 'file')"
+                                style="margin-right:5px;margin-left:15px;">
+                            <span>Select All</span>
+                        </button>
+                        <button mat-button mat-raised-button class="mat-basic small-button"
+                                (click)="deselectAll(files, fileIdFunction)"
+                                style="margin-right:10px;margin-left:5px;">
+                            <span>Deselect All</span>
+                        </button>
+                    </div>
+                </div>
+                <div *ngFor="let element of files" fxLayout="row">
+                    <mat-checkbox color="accent"
+                                  [checked]="linkSelected(element.fileId)"
+                                  (change)="selectLink($event.checked, element.fileId, element.originalFilename, 'file')">
+                        {{element.originalFilename}}
+                    </mat-checkbox>
+                </div>
+            </div>
+            <div fxLayout="column" class="link-configuration">
+                <div fxLayout="row" fxLayoutAlign="start center" class="mb-10">
+                    <div fxLayout="row" fxLayoutAlign="start center">
+                        <span class="general-options-header mb-0">Pipelines</span>
+                    </div>
+                    <div fxLayout="row" fxLayoutAlign="end center" fxFlex>
+                        <button mat-button mat-raised-button color="accent" class="small-button"
+                                (click)="selectAll(pipelines, idFunction, nameFunction, 'pipeline')"
+                                style="margin-right:5px;margin-left:15px;">
+                            <span>Select All</span>
+                        </button>
+                        <button mat-button mat-raised-button class="mat-basic small-button"
+                                (click)="deselectAll(pipelines, idFunction)"
+                                style="margin-right:10px;margin-left:5px;">
+                            <span>Deselect All</span>
+                        </button>
+                    </div>
+                </div>
+                <div *ngFor="let pipeline of pipelines" fxLayout="row">
+                    <mat-checkbox color="accent" [checked]="linkSelected(pipeline._id)"
+                                  (change)="selectLink($event.checked, pipeline._id, pipeline.name, 'pipeline')">{{pipeline.name}}</mat-checkbox>
+                </div>
+            </div>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                (click)="store()" style="margin-right:10px;">
+            Update links
+        </button>
+        <button mat-button mat-raised-button class="mat-basic" (click)="cancel()" style="margin-right:10px;">
+            Cancel
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.scss
similarity index 81%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.scss
index a375af7..c7debbd 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.scss
@@ -16,7 +16,16 @@
  *
  */
 
-.md-padding {
+@import 'src/scss/sp/sp-dialog';
+
+.link-configuration {
   padding: 10px;
+  width:100%;
+  margin:5px;
+  background: var(--color-bg-1);
+  border: 1px solid var(--color-bg-3);
 }
 
+.mb-0 {
+  margin-bottom: 0;
+}
diff --git a/ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.ts b/ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.ts
new file mode 100644
index 0000000..320bf83
--- /dev/null
+++ b/ui/src/app/assets/dialog/manage-asset-links/manage-asset-links-dialog.component.ts
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import { DialogRef } from '@streampipes/shared-ui';
+import {
+  AdapterDescriptionUnion,
+  SpDataStream,
+  AdapterService,
+  AssetLink,
+  AssetLinkType,
+  Dashboard,
+  DashboardService,
+  DataLakeMeasure, DatalakeRestService,
+  DataViewDataExplorerService,
+  GenericStorageService,
+  Pipeline,
+  PipelineService,
+  PipelineElementService, FileMetadata, FilesService
+} from '@streampipes/platform-services';
+import { FormGroup } from '@angular/forms';
+import { zip } from 'rxjs';
+import { MatSelectChange } from '@angular/material/select';
+import { BaseAssetLinksDirective } from '../base-asset-links.directive';
+
+@Component({
+  selector: 'sp-manage-asset-links-dialog-component',
+  templateUrl: './manage-asset-links-dialog.component.html',
+  styleUrls: ['./manage-asset-links-dialog.component.scss']
+})
+export class SpManageAssetLinksDialogComponent extends BaseAssetLinksDirective implements OnInit {
+
+  @Input()
+  assetLinks: AssetLink[];
+
+  @Input()
+  assetLinkTypes: AssetLinkType[];
+
+  clonedAssetLinks: AssetLink[] = [];
+
+  idFunction = (el) => el._id;
+  elementIdFunction = (el) => el.elementId;
+  fileIdFunction = (el) => el.fileId;
+  nameFunction = (el) => el.name;
+  filenameFunction = (el) => el.originalFilename;
+  measureNameFunction = (el) => el.measureName;
+
+
+  constructor(private dialogRef: DialogRef<SpManageAssetLinksDialogComponent>,
+              protected genericStorageService: GenericStorageService,
+              protected pipelineService: PipelineService,
+              protected dataViewService: DataViewDataExplorerService,
+              protected dashboardService: DashboardService,
+              protected dataLakeService: DatalakeRestService,
+              protected pipelineElementService: PipelineElementService,
+              protected adapterService: AdapterService,
+              protected filesService: FilesService) {
+    super(
+      genericStorageService,
+      pipelineService,
+      dataViewService,
+      dashboardService,
+      dataLakeService,
+      pipelineElementService,
+      adapterService,
+      filesService);
+  }
+
+  ngOnInit(): void {
+    super.onInit();
+    this.clonedAssetLinks = [
+      ...this.assetLinks.map(al => {
+        return {...al};
+      })
+    ];
+  }
+
+  cancel(): void {
+    this.dialogRef.close();
+  }
+
+  store(): void {
+    this.assetLinks = this.clonedAssetLinks;
+    this.dialogRef.close(this.assetLinks);
+  }
+
+  afterResourcesLoaded(): void {
+  }
+
+  linkSelected(resourceId: string): boolean {
+    return this.clonedAssetLinks.find(al => al.resourceId === resourceId) !== undefined;
+  }
+
+  selectLink(checked: boolean,
+             resourceId: string,
+             label: string,
+             assetLinkType: string): void {
+    if (checked) {
+      this.clonedAssetLinks.push(this.makeLink(resourceId, label, assetLinkType));
+    } else {
+      const index = this.clonedAssetLinks.findIndex(al => al.resourceId === resourceId);
+      this.clonedAssetLinks.splice(index, 1);
+    }
+  }
+
+  makeLink(resourceId: string,
+           label: string,
+           assetLinkType: string): AssetLink {
+
+    const linkType = this.assetLinkTypes.find(a => a.linkType === assetLinkType);
+    return {
+      linkLabel: label,
+      linkType: linkType.linkType,
+      editingDisabled: false,
+      queryHint: linkType.linkQueryHint,
+      navigationActive: linkType.navigationActive,
+      resourceId
+    };
+  }
+
+  selectAll(elements: any[],
+            idFunction: any,
+            nameFunction: any,
+            assetLinkType: string): void {
+    elements.forEach(el => {
+      const id = idFunction(el);
+      const elementName = nameFunction(el);
+      if (!this.linkSelected(id)) {
+        this.selectLink(true, id, elementName, assetLinkType);
+      }
+    });
+  }
+
+  deselectAll(elements: any[],
+              idFunction: any): void {
+    elements.forEach(el => {
+      const id = idFunction(el);
+      const index = this.clonedAssetLinks.findIndex(al => al.resourceId === id);
+      if (index > -1) {
+        this.clonedAssetLinks.splice(index, 1);
+      }
+    });
+  }
+}
diff --git a/ui/src/app/configuration/configuration-tabs.ts b/ui/src/app/configuration/configuration-tabs.ts
new file mode 100644
index 0000000..367d7a9
--- /dev/null
+++ b/ui/src/app/configuration/configuration-tabs.ts
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { SpNavigationItem } from '@streampipes/shared-ui';
+
+export class SpConfigurationTabs {
+
+  public static getTabs(): SpNavigationItem[] {
+    return [
+      {itemId: 'general', itemTitle: 'General', itemLink: ['configuration', 'general']},
+      {itemId: 'datalake', itemTitle: 'Data Lake', itemLink: ['configuration', 'datalake']},
+      {itemId: 'email', itemTitle: 'Mail', itemLink: ['configuration', 'email']},
+      {itemId: 'export', itemTitle: 'Export/Import', itemLink: ['configuration', 'export']},
+      {itemId: 'messaging', itemTitle: 'Messaging', itemLink: ['configuration', 'messaging']},
+      {itemId: 'pipelineelement', itemTitle: 'Pipeline Element Configuration', itemLink: ['configuration', 'pipelineelement']},
+      {itemId: 'security', itemTitle: 'Security', itemLink: ['configuration', 'security']}
+    ];
+  }
+}
diff --git a/ui/src/app/configuration/configuration.component.html b/ui/src/app/configuration/configuration.component.html
deleted file mode 100644
index 026c76f..0000000
--- a/ui/src/app/configuration/configuration.component.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--

-  ~ Licensed to the Apache Software Foundation (ASF) under one or more

-  ~ contributor license agreements.  See the NOTICE file distributed with

-  ~ this work for additional information regarding copyright ownership.

-  ~ The ASF licenses this file to You under the Apache License, Version 2.0

-  ~ (the "License"); you may not use this file except in compliance with

-  ~ the License.  You may obtain a copy of the License at

-  ~

-  ~    http://www.apache.org/licenses/LICENSE-2.0

-  ~

-  ~ Unless required by applicable law or agreed to in writing, software

-  ~ distributed under the License is distributed on an "AS IS" BASIS,

-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-  ~ See the License for the specific language governing permissions and

-  ~ limitations under the License.

-  ~

-  -->

-

-<div fxLayout="column" class="page-container">

-    <div fxLayout="row" class="p-0 sp-bg-lightgray page-container-nav">

-        <div fxLayout="fill">

-            <mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="selectedIndexChange($event)"

-                           color="accent">

-                <mat-tab label="General"></mat-tab>

-                <mat-tab label="DataLake"></mat-tab>

-                <mat-tab label="Mail"></mat-tab>

-                <mat-tab label="Messaging"></mat-tab>

-                <mat-tab label="Pipeline Element Configuration"></mat-tab>

-                <mat-tab label="Security"></mat-tab>

-            </mat-tab-group>

-        </div>

-    </div>

-

-    <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100">

-        <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100"

-             *ngIf="selectedIndex == 0">

-            <sp-general-configuration fxFlex="100"></sp-general-configuration>

-        </div>

-        <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100"

-             *ngIf="selectedIndex == 1">

-            <sp-datalake-configuration fxFlex="100"></sp-datalake-configuration>

-        </div>

-        <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100"

-             *ngIf="selectedIndex == 2">

-            <sp-email-configuration fxFlex="100"></sp-email-configuration>

-        </div>

-        <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100"

-             *ngIf="selectedIndex == 3">

-            <messaging-configuration fxFlex="100"></messaging-configuration>

-        </div>

-        <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100"

-             *ngIf="selectedIndex == 4">

-            <pipeline-element-configuration fxFlex="100"></pipeline-element-configuration>

-        </div>

-        <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100"

-             *ngIf="selectedIndex == 5">

-            <sp-security-configuration fxFlex="100"></sp-security-configuration>

-        </div>

-    </div>

-

-</div>

diff --git a/ui/src/app/configuration/configuration.component.spec.ts b/ui/src/app/configuration/configuration.component.spec.ts
deleted file mode 100644
index 21ca1ca..0000000
--- a/ui/src/app/configuration/configuration.component.spec.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *    http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- *

- */

-

-import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';

-import { ConfigurationComponent } from './configuration.component';

-import { CommonModule } from '@angular/common';

-import { FlexLayoutModule } from '@angular/flex-layout';

-import { ConfigurationService } from './shared/configuration.service';

-import { ConfigurationMockService } from './shared/configuration.test.service';

-import { NO_ERRORS_SCHEMA } from '@angular/core';

-

-describe('ConfigurationComponent', () => {

-

-  let fixture: ComponentFixture<ConfigurationComponent>;

-  let configurationComponent: ConfigurationComponent;

-

-  beforeEach(waitForAsync(() => {

-    TestBed.configureTestingModule({

-      imports: [

-        CommonModule,

-        FlexLayoutModule

-      ],

-      declarations: [

-        ConfigurationComponent

-      ],

-      providers: [

-        { provide: ConfigurationService, useClass: ConfigurationMockService }

-      ],

-      schemas: [

-        NO_ERRORS_SCHEMA

-      ]

-    }).compileComponents();

-    fixture = TestBed.createComponent(ConfigurationComponent);

-    fixture.detectChanges();

-    configurationComponent = fixture.componentInstance;

-  }));

-

-  it('should create the component', waitForAsync(() => {

-    expect(configurationComponent).toBeTruthy();

-  }));

-

-});

diff --git a/ui/src/app/configuration/configuration.component.ts b/ui/src/app/configuration/configuration.component.ts
deleted file mode 100644
index fdf7d4d..0000000
--- a/ui/src/app/configuration/configuration.component.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *    http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- *

- */

-

-import { Component } from '@angular/core';

-import { animate, state, style, transition, trigger } from '@angular/animations';

-

-@Component({

-    templateUrl: './configuration.component.html',

-    styleUrls: ['./configuration.component.css'],

-    animations: [

-        trigger('detailExpand', [

-            state('collapsed', style({height: '0px', minHeight: '0', display: 'none'})),

-            state('expanded', style({height: '*'})),

-            transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),

-        ]),

-    ]

-})

-export class ConfigurationComponent {

-

-    selectedIndex = 0;

-

-    constructor() {

-    }

-

-    selectedIndexChange(index: number) {

-        this.selectedIndex = index;

-    }

-

-}

diff --git a/ui/src/app/configuration/configuration.module.ts b/ui/src/app/configuration/configuration.module.ts
index 864d918..1aa5060 100644
--- a/ui/src/app/configuration/configuration.module.ts
+++ b/ui/src/app/configuration/configuration.module.ts
@@ -26,8 +26,6 @@
 import { FlexLayoutModule } from '@angular/flex-layout';

 import { CommonModule } from '@angular/common';

 import { FormsModule, ReactiveFormsModule } from '@angular/forms';

-

-import { ConfigurationComponent } from './configuration.component';

 import { ConfigurationService } from './shared/configuration.service';

 import { ConsulServiceComponent } from './consul-service/consul-service.component';

 import { ConsulConfigsComponent } from './consul-configs/consul-configs.component';

@@ -53,9 +51,13 @@
 import { EditGroupDialogComponent } from './security-configuration/edit-group-dialog/edit-group-dialog.component';

 import { EmailConfigurationComponent } from './email-configuration/email-configuration.component';

 import { GeneralConfigurationComponent } from './general-configuration/general-configuration.component';

-import {

-  SecurityAuthenticationConfigurationComponent

-} from './security-configuration/authentication-configuration/authentication-configuration.component';

+import { SecurityAuthenticationConfigurationComponent } from './security-configuration/authentication-configuration/authentication-configuration.component';

+import { RouterModule } from '@angular/router';

+import { SharedUiModule } from '@streampipes/shared-ui';

+import { SpDataExportImportComponent } from './export/data-export-import.component';

+import { SpDataExportDialogComponent } from './export/export-dialog/data-export-dialog.component';

+import { SpDataImportDialogComponent } from './export/import-dialog/data-import-dialog.component';

+import { SpDataExportItemComponent } from './export/export-dialog/data-export-item/data-export-item.component';

 

 @NgModule({

   imports: [

@@ -75,9 +77,49 @@
     CoreUiModule,

     ReactiveFormsModule,

     PlatformServicesModule,

+    RouterModule.forChild([

+      {

+        path: 'configuration',

+        children: [

+          {

+            path: '',

+            redirectTo: 'general',

+            pathMatch: 'full'

+          },

+          {

+            path: 'general',

+            component: GeneralConfigurationComponent

+          },

+          {

+            path: 'datalake',

+            component: DatalakeConfigurationComponent

+          },

+          {

+            path: 'email',

+            component: EmailConfigurationComponent

+          },

+          {

+            path: 'export',

+            component: SpDataExportImportComponent

+          },

+          {

+            path: 'messaging',

+            component: MessagingConfigurationComponent

+          },

+          {

+            path: 'pipelineelement',

+            component: PipelineElementConfigurationComponent

+          },

+          {

+            path: 'security',

+            component: SecurityConfigurationComponent

+          }

+        ]

+      }

+    ]),

+    SharedUiModule,

   ],

   declarations: [

-    ConfigurationComponent,

     ConsulServiceComponent,

     ConsulConfigsComponent,

     ConsulConfigsTextComponent,

@@ -97,10 +139,11 @@
     SecurityServiceConfigComponent,

     MessagingConfigurationComponent,

     DatalakeConfigurationComponent,

+    SpDataExportImportComponent,

+    SpDataExportDialogComponent,

+    SpDataExportItemComponent,

+    SpDataImportDialogComponent

   ],

-  providers: [

-    ConfigurationService,

-  ]

+  providers: [ConfigurationService],

 })

-export class ConfigurationModule {

-}

+export class ConfigurationModule {}

diff --git a/ui/src/app/configuration/configuration.component.css b/ui/src/app/configuration/configuration.routes.ts
similarity index 79%
rename from ui/src/app/configuration/configuration.component.css
rename to ui/src/app/configuration/configuration.routes.ts
index cd8f273..79ce64b 100644
--- a/ui/src/app/configuration/configuration.component.css
+++ b/ui/src/app/configuration/configuration.routes.ts
@@ -1,22 +1,25 @@
-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *    http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- *

- */

-

-.page-container-padding-inner {

-    padding: 10px;

-}

-

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+
+export class SpConfigurationRoutes {
+
+  static CONFIGURATION_BASE_LINK = 'configuration';
+  static BASE: SpBreadcrumbItem = {label: 'Configuration'};
+}
diff --git a/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.html b/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.html
index bbc29d5..a967e01 100644
--- a/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.html
+++ b/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.html
@@ -16,95 +16,109 @@
   ~
   -->
 
-<div fxLayout="row" class="page-container-padding">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
-        <sp-split-section title="Data Lake Settings"
-                          subtitle="Truncate and delete persisted data streams">
-            <div fxFlex="100" fxLayout="column">
-                <div class="subsection-title">Existing data lake indices</div>
-                <table
-                        fxFlex="100"
-                        mat-table
-                        data-cy="datalake-settings"
-                        [dataSource]="dataSource"
-                        style="width: 100%;"
-                        matSort>
 
-                    <ng-container matColumnDef="name">
-                        <th mat-header-cell mat-sort-header *matHeaderCellDef>Name</th>
-                        <td mat-cell *matCellDef="let configurationEntry">
-                            <h4 style="margin-bottom:0px;">{{configurationEntry.name}}</h4>
-                        </td>
-                    </ng-container>
+<sp-basic-nav-tabs [spNavigationItems]="tabs" [activeLink]="'datalake'">
+    <div fxLayout="row" class="page-container-padding">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section title="Data Lake Settings" subtitle="Truncate and delete persisted data streams">
+                <div fxFlex="100" fxLayout="column">
+                    <div fxFlex="100" fxLayout="row">
+                        <div fxFlex fxLayoutAlign="start center" class="subsection-title">Existing data lake indices</div>
+                        <div fxLayout="row" fxLayoutAlign="end center">
+                            <button color="accent"
+                                    mat-button
+                                    mat-icon-button
+                                    matTooltip="Refresh Schema"
+                                    (click)="loadAvailableMeasurements()">
+                                <mat-icon>refresh</mat-icon>
+                            </button>
+                        </div>
+                    </div>
+                    <table fxFlex="100" mat-table data-cy="datalake-settings" [dataSource]="dataSource"
+                        style="width: 100%;" matSort>
 
-                    <ng-container matColumnDef="pipeline">
-                        <th mat-header-cell mat-sort-header *matHeaderCellDef>Related Pipeline</th>
-                        <td mat-cell *matCellDef="let configurationEntry">
-                            {{configurationEntry.pipelines}}
-                        </td>
-                    </ng-container>
+                        <ng-container matColumnDef="name">
+                            <th mat-header-cell mat-sort-header *matHeaderCellDef>Name</th>
+                            <td mat-cell *matCellDef="let configurationEntry">
+                                <h4 style="margin-bottom:0px;">{{configurationEntry.name}}</h4>
+                            </td>
+                        </ng-container>
 
-                    <ng-container matColumnDef="events">
-                        <th mat-header-cell mat-sort-header *matHeaderCellDef># Events</th>
-                        <td
-                                mat-cell
-                                data-cy="datalake-number-of-events"
-                                *matCellDef="let configurationEntry">
-                            {{configurationEntry.events | number}}
-                        </td>
-                    </ng-container>
+                        <ng-container matColumnDef="pipeline">
+                            <th mat-header-cell mat-sort-header *matHeaderCellDef>Related Pipeline</th>
+                            <td mat-cell *matCellDef="let configurationEntry">
+                                {{configurationEntry.pipelines}}
+                            </td>
+                        </ng-container>
 
-                    <ng-container matColumnDef="truncate">
-                        <th mat-header-cell *matHeaderCellDef>Truncate</th>
-                        <td mat-cell *matCellDef="let configurationEntry">
-                            <div fxLayout="row">
-                            <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center">
-                                    <button color="accent"
-                                            mat-button
-                                            mat-icon-button
-                                            matTooltip="Truncate all data from index"
-                                            matTooltipPosition="above"
+                        <ng-container matColumnDef="events">
+                            <th mat-header-cell mat-sort-header *matHeaderCellDef># Events</th>
+                            <td mat-cell data-cy="datalake-number-of-events" *matCellDef="let configurationEntry">
+                                {{configurationEntry.events | number}}
+                            </td>
+                        </ng-container>
+
+                        <ng-container matColumnDef="download">
+                            <th mat-header-cell *matHeaderCellDef>Download</th>
+                            <td mat-cell *matCellDef="let configurationEntry">
+                                <div fxLayout="row">
+                                    <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="start center">
+                                        <button color="accent" mat-button mat-icon-button
+                                                matTooltip="Download data from index" matTooltipPosition="above"
+                                                data-cy="datalake-download-btn"
+                                                (click)="openDownloadDialog(configurationEntry.name)">
+                                            <i class="material-icons">download</i>
+                                        </button>
+                                    </span>
+                                </div>
+                            </td>
+                        </ng-container>
+
+                        <ng-container matColumnDef="truncate">
+                            <th mat-header-cell *matHeaderCellDef>Truncate</th>
+                            <td mat-cell *matCellDef="let configurationEntry">
+                                <div fxLayout="row">
+                                    <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="start center">
+                                        <button color="accent" mat-button mat-icon-button
+                                            matTooltip="Truncate all data from index" matTooltipPosition="above"
                                             data-cy="datalake-truncate-btn"
                                             (click)="cleanDatalakeIndex(configurationEntry.name)">
-                                        <i class="material-icons">local_fire_department</i>
-                                    </button>
-                                </span>
-                            </div>
-                        </td>
-                    </ng-container>
+                                            <i class="material-icons">local_fire_department</i>
+                                        </button>
+                                    </span>
+                                </div>
+                            </td>
+                        </ng-container>
 
-                    <ng-container matColumnDef="remove">
-                        <th mat-header-cell *matHeaderCellDef>Remove</th>
-                        <td mat-cell *matCellDef="let configurationEntry">
-                            <div fxLayout="row">
-                            <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center">
-                                    <button color="accent"
-                                            mat-button
-                                            mat-icon-button
-                                            matTooltip="Remove index from database"
-                                            data-cy="datalake-delete-btn"
-                                            matTooltipPosition="above"
-                                            [disabled]="!configurationEntry.remove"
+                        <ng-container matColumnDef="remove">
+                            <th mat-header-cell *matHeaderCellDef>Remove</th>
+                            <td mat-cell *matCellDef="let configurationEntry">
+                                <div fxLayout="row">
+                                    <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="start center">
+                                        <button color="accent" mat-button mat-icon-button
+                                            matTooltip="Remove index from database" data-cy="datalake-delete-btn"
+                                            matTooltipPosition="above" [disabled]="!configurationEntry.remove"
                                             (click)="deleteDatalakeIndex(configurationEntry.name)">
-                                        <i class="material-icons">delete</i>
-                                    </button>
-                                </span>
-                            </div>
-                        </td>
-                    </ng-container>
+                                            <i class="material-icons">delete</i>
+                                        </button>
+                                    </span>
+                                </div>
+                            </td>
+                        </ng-container>
 
-                    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
-                    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+                        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
 
-                </table>
-            </div>
-            <div fxFlex="100" fxLayoutAlign="end end">
-                <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]="20"></mat-paginator>
-            </div>
-            <div fxFlex="100" fxLayout="column" fxLayoutAlign="center center" *ngIf="availableMeasurements.length == 0">
-                <h5>(no stored measurements)</h5>
-            </div>
-        </sp-split-section>
+                    </table>
+                </div>
+                <div fxFlex="100" fxLayoutAlign="end end">
+                    <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]="20"></mat-paginator>
+                </div>
+                <div fxFlex="100" fxLayout="column" fxLayoutAlign="center center"
+                    *ngIf="availableMeasurements.length == 0">
+                    <h5>(no stored measurements)</h5>
+                </div>
+            </sp-split-section>
+        </div>
     </div>
-</div>
-
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.ts b/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.ts
index 7f6986d..d1792ac 100644
--- a/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.ts
+++ b/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.ts
@@ -20,18 +20,22 @@
 import { MatTableDataSource } from '@angular/material/table';
 import { DataLakeConfigurationEntry } from './datalake-configuration-entry';
 import {
+  DataExplorerDataConfig,
   DatalakeQueryParameterBuilder,
   DatalakeQueryParameters,
   DatalakeRestService,
-  DataViewDataExplorerService,
+  DataViewDataExplorerService, DateRange,
   EventSchema,
   FieldConfig,
   SpQueryResult
 } from '@streampipes/platform-services';
 import { MatPaginator } from '@angular/material/paginator';
 import { MatSort } from '@angular/material/sort';
-import { DialogRef, DialogService, PanelType } from '@streampipes/shared-ui';
+import { DialogRef, DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
 import { DeleteDatalakeIndexComponent } from '../dialog/delete-datalake-index/delete-datalake-index-dialog.component';
+import { SpConfigurationTabs } from '../configuration-tabs';
+import { SpConfigurationRoutes } from '../configuration.routes';
+import { DataDownloadDialogComponent } from '../../core-ui/data-download-dialog/data-download-dialog.component';
 
 @Component({
   selector: 'sp-datalake-configuration',
@@ -40,6 +44,8 @@
 })
 export class DatalakeConfigurationComponent implements OnInit {
 
+  tabs = SpConfigurationTabs.getTabs();
+
   @ViewChild(MatPaginator) paginator: MatPaginator;
   pageSize = 1;
   @ViewChild(MatSort) sort: MatSort;
@@ -47,16 +53,18 @@
   dataSource: MatTableDataSource<DataLakeConfigurationEntry>;
   availableMeasurements: DataLakeConfigurationEntry[] = [];
 
-  displayedColumns: string[] = ['name', 'pipeline', 'events', 'truncate', 'remove'];
+  displayedColumns: string[] = ['name', 'pipeline', 'events', 'download', 'truncate', 'remove'];
 
   constructor(
     // protected dataLakeRestService: DatalakeRestService,
     private datalakeRestService: DatalakeRestService,
     private dataViewDataExplorerService: DataViewDataExplorerService,
-    private dialogService: DialogService) {
+    private dialogService: DialogService,
+    private breadcrumbService: SpBreadcrumbService) {
   }
 
   ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb([SpConfigurationRoutes.BASE, {label: SpConfigurationTabs.getTabs()[1].itemTitle}]);
     this.loadAvailableMeasurements();
   }
 
@@ -147,6 +155,17 @@
     });
   }
 
+  openDownloadDialog(measurementName: string) {
+    this.dialogService.open(DataDownloadDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Download data',
+      width: '50vw',
+      data: {
+        'measureName': measurementName,
+      }
+    });
+  }
+
   private buildQ(column: FieldConfig): DatalakeQueryParameters {
     return DatalakeQueryParameterBuilder.create(0, new Date().getTime())
       .withColumnFilter([column], true)
diff --git a/ui/src/app/configuration/email-configuration/email-configuration.component.html b/ui/src/app/configuration/email-configuration/email-configuration.component.html
index f1ddd7e..b6994e3 100644
--- a/ui/src/app/configuration/email-configuration/email-configuration.component.html
+++ b/ui/src/app/configuration/email-configuration/email-configuration.component.html
@@ -16,114 +16,101 @@
   ~
   -->
 
-<div fxLayout="column" class="page-container-padding">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" *ngIf="formReady">
-        <sp-split-section title="Mail Settings"
-                          subtitle="Settings to connect to a mail server">
-            <form [formGroup]="parentForm" fxFlex="100" fxLayout="column">
-                <div class="subsection-title">Mail Server</div>
-                <mat-form-field color="accent">
-                    <mat-label>SMTP Host</mat-label>
-                    <input formControlName="smtpServerHost" fxFlex
-                           matInput
-                           required>
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>SMTP Port</mat-label>
-                    <input type="number" formControlName="smtpServerPort" fxFlex
-                           matInput
-                           required>
-                </mat-form-field>
-                <div class="subsection-title">Transport</div>
-                <mat-radio-group fxLayout="column" formControlName="transport">
-                    <mat-radio-button value="SMTP" class="m-5">SMTP</mat-radio-button>
-                    <mat-radio-button value="SMTPS" class="m-5">SMTPS</mat-radio-button>
-                    <mat-radio-button value="SMTP_TLS" class="m-5">TLS</mat-radio-button>
-                </mat-radio-group>
-                <div class="subsection-title mt-20">Authentication</div>
-                <mat-checkbox formControlName="usesAuthentication">SMTP server requires authentication</mat-checkbox>
-                <mat-form-field color="accent" *ngIf="mailConfig.usesAuthentication">
-                    <mat-label>SMTP Username</mat-label>
-                    <input formControlName="smtpUsername" fxFlex
-                           matInput>
-                </mat-form-field>
-                <mat-form-field color="accent" *ngIf="mailConfig.usesAuthentication">
-                    <mat-label>SMTP Password</mat-label>
-                    <input formControlName="smtpPassword" fxFlex type="password"
-                           matInput>
-                </mat-form-field>
-                <div class="subsection-title mt-20">Proxy</div>
-                <mat-checkbox formControlName="usesProxy">Uses proxy</mat-checkbox>
-                <mat-form-field color="accent" *ngIf="mailConfig.usesProxy">
-                    <mat-label>Proxy Host</mat-label>
-                    <input formControlName="proxyHost" fxFlex
-                           matInput>
-                </mat-form-field>
-                <mat-form-field color="accent" *ngIf="mailConfig.usesProxy">
-                    <mat-label>Proxy Port</mat-label>
-                    <input formControlName="proxyPort" fxFlex
-                           matInput>
-                </mat-form-field>
-                <mat-checkbox formControlName="usesProxyAuthentication" *ngIf="mailConfig.usesProxy">
-                    Proxy requires authentication
-                </mat-checkbox>
-                <mat-form-field color="accent" *ngIf="mailConfig.usesProxy && mailConfig.usesProxyAuthentication">
-                    <mat-label>Proxy Username</mat-label>
-                    <input formControlName="proxyUsername" fxFlex
-                           matInput>
-                </mat-form-field>
-                <mat-form-field color="accent" *ngIf="mailConfig.usesProxy && mailConfig.usesProxyAuthentication">
-                    <mat-label>Proxy Password</mat-label>
-                    <input formControlName="proxyPassword" fxFlex type="password"
-                           matInput>
-                </mat-form-field>
-                <div class="subsection-title mt-20">Sender</div>
-                <mat-form-field color="accent">
-                    <mat-label>Sender Email Address</mat-label>
-                    <input formControlName="senderAddress" fxFlex
-                           matInput
-                           required>
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>Sender Name</mat-label>
-                    <input formControlName="senderName" fxFlex
-                           matInput>
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>Recipient for test mail</mat-label>
-                    <input formControlName="defaultRecipient" fxFlex
-                           matInput>
-                </mat-form-field>
-                <div fxLayout="row">
-                <button mat-button mat-raised-button color="accent" (click)="save()" style="margin-right:10px;"
-                        [disabled]="!parentForm.valid"
-                        data-cy="sp-element-email-config-save">
-                    <i class="material-icons">save</i><span>&nbsp;Save</span>
-                </button>
-                <button mat-button mat-raised-button class="mat-basic" (click)="sendTestMail()" style="margin-right:10px;"
-                        [disabled]="!parentForm.valid || sendingTestMailInProgress"
-                        data-cy="sp-element-email-config-test">
-                    <span>Send Test Mail</span>
-                </button>
-                </div>
-                <div fxLayout="column" *ngIf="attemptSendingTestMail">
-                    <div fxLayout="row" *ngIf="sendingTestMailInProgress">
-                        <mat-progress-spinner diameter="10"></mat-progress-spinner>
-                        <h5>Trying to send test mail...</h5>
-                    </div>
+<sp-basic-nav-tabs [spNavigationItems]="tabs" [activeLink]="'email'">
+    <div fxLayout="column" class="page-container-padding">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" *ngIf="formReady">
+            <sp-split-section title="Mail Settings" subtitle="Settings to connect to a mail server">
+                <form [formGroup]="parentForm" fxFlex="100" fxLayout="column">
+                    <div class="subsection-title">Mail Server</div>
+                    <mat-form-field color="accent">
+                        <mat-label>SMTP Host</mat-label>
+                        <input formControlName="smtpServerHost" fxFlex matInput required>
+                    </mat-form-field>
+                    <mat-form-field color="accent">
+                        <mat-label>SMTP Port</mat-label>
+                        <input type="number" formControlName="smtpServerPort" fxFlex matInput required>
+                    </mat-form-field>
+                    <div class="subsection-title">Transport</div>
+                    <mat-radio-group fxLayout="column" formControlName="transport">
+                        <mat-radio-button value="SMTP" class="m-5">SMTP</mat-radio-button>
+                        <mat-radio-button value="SMTPS" class="m-5">SMTPS</mat-radio-button>
+                        <mat-radio-button value="SMTP_TLS" class="m-5">TLS</mat-radio-button>
+                    </mat-radio-group>
+                    <div class="subsection-title mt-20">Authentication</div>
+                    <mat-checkbox formControlName="usesAuthentication">SMTP server requires authentication
+                    </mat-checkbox>
+                    <mat-form-field color="accent" *ngIf="mailConfig.usesAuthentication">
+                        <mat-label>SMTP Username</mat-label>
+                        <input formControlName="smtpUsername" fxFlex matInput>
+                    </mat-form-field>
+                    <mat-form-field color="accent" *ngIf="mailConfig.usesAuthentication">
+                        <mat-label>SMTP Password</mat-label>
+                        <input formControlName="smtpPassword" fxFlex type="password" matInput>
+                    </mat-form-field>
+                    <div class="subsection-title mt-20">Proxy</div>
+                    <mat-checkbox formControlName="usesProxy">Uses proxy</mat-checkbox>
+                    <mat-form-field color="accent" *ngIf="mailConfig.usesProxy">
+                        <mat-label>Proxy Host</mat-label>
+                        <input formControlName="proxyHost" fxFlex matInput>
+                    </mat-form-field>
+                    <mat-form-field color="accent" *ngIf="mailConfig.usesProxy">
+                        <mat-label>Proxy Port</mat-label>
+                        <input formControlName="proxyPort" fxFlex matInput>
+                    </mat-form-field>
+                    <mat-checkbox formControlName="usesProxyAuthentication" *ngIf="mailConfig.usesProxy">
+                        Proxy requires authentication
+                    </mat-checkbox>
+                    <mat-form-field color="accent" *ngIf="mailConfig.usesProxy && mailConfig.usesProxyAuthentication">
+                        <mat-label>Proxy Username</mat-label>
+                        <input formControlName="proxyUsername" fxFlex matInput>
+                    </mat-form-field>
+                    <mat-form-field color="accent" *ngIf="mailConfig.usesProxy && mailConfig.usesProxyAuthentication">
+                        <mat-label>Proxy Password</mat-label>
+                        <input formControlName="proxyPassword" fxFlex type="password" matInput>
+                    </mat-form-field>
+                    <div class="subsection-title mt-20">Sender</div>
+                    <mat-form-field color="accent">
+                        <mat-label>Sender Email Address</mat-label>
+                        <input formControlName="senderAddress" fxFlex matInput required>
+                    </mat-form-field>
+                    <mat-form-field color="accent">
+                        <mat-label>Sender Name</mat-label>
+                        <input formControlName="senderName" fxFlex matInput>
+                    </mat-form-field>
+                    <mat-form-field color="accent">
+                        <mat-label>Recipient for test mail</mat-label>
+                        <input formControlName="defaultRecipient" fxFlex matInput>
+                    </mat-form-field>
                     <div fxLayout="row">
-                        <h5 *ngIf="!sendingTestMailInProgress && sendingTestMailSuccess">Success - please check your mail inbox.</h5>
-                        <div fxLayout="column" *ngIf="!sendingTestMailInProgress && !sendingTestMailSuccess">
-                            Failure
-                            <h5>{{sendingEmailErrorMessage}}</h5>
+                        <button mat-button mat-raised-button color="accent" (click)="save()" style="margin-right:10px;"
+                            [disabled]="!parentForm.valid" data-cy="sp-element-email-config-save">
+                            <i class="material-icons">save</i><span>&nbsp;Save</span>
+                        </button>
+                        <button mat-button mat-raised-button class="mat-basic" (click)="sendTestMail()"
+                            style="margin-right:10px;" [disabled]="!parentForm.valid || sendingTestMailInProgress"
+                            data-cy="sp-element-email-config-test">
+                            <span>Send Test Mail</span>
+                        </button>
+                    </div>
+                    <div fxLayout="column" *ngIf="attemptSendingTestMail">
+                        <div fxLayout="row" *ngIf="sendingTestMailInProgress">
+                            <mat-progress-spinner diameter="10"></mat-progress-spinner>
+                            <h5>Trying to send test mail...</h5>
+                        </div>
+                        <div fxLayout="row">
+                            <h5 *ngIf="!sendingTestMailInProgress && sendingTestMailSuccess">Success - please check your
+                                mail inbox.</h5>
+                            <div fxLayout="column" *ngIf="!sendingTestMailInProgress && !sendingTestMailSuccess">
+                                Failure
+                                <h5>{{sendingEmailErrorMessage}}</h5>
+                            </div>
                         </div>
                     </div>
-                </div>
-            </form>
-        </sp-split-section>
+                </form>
+            </sp-split-section>
+        </div>
+        <mat-divider></mat-divider>
+
+
     </div>
-    <mat-divider></mat-divider>
-
-
-</div>
-
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/configuration/email-configuration/email-configuration.component.ts b/ui/src/app/configuration/email-configuration/email-configuration.component.ts
index 698780c..4c49b40 100644
--- a/ui/src/app/configuration/email-configuration/email-configuration.component.ts
+++ b/ui/src/app/configuration/email-configuration/email-configuration.component.ts
@@ -19,6 +19,9 @@
 import { Component, OnInit } from '@angular/core';
 import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
 import { EmailConfig, MailConfigService } from '@streampipes/platform-services';
+import { SpConfigurationTabs } from '../configuration-tabs';
+import { SpConfigurationRoutes } from '../configuration.routes';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
 
 @Component({
   selector: 'sp-email-configuration',
@@ -27,6 +30,8 @@
 })
 export class EmailConfigurationComponent implements OnInit {
 
+  tabs = SpConfigurationTabs.getTabs();
+
   parentForm: FormGroup;
 
   mailConfig: EmailConfig;
@@ -39,9 +44,11 @@
   sendingEmailErrorMessage = '';
 
   constructor(private fb: FormBuilder,
-              private mailConfigService: MailConfigService) {}
+              private mailConfigService: MailConfigService,
+              private breadcrumbService: SpBreadcrumbService) {}
 
   ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb([SpConfigurationRoutes.BASE, {label: SpConfigurationTabs.getTabs()[2].itemTitle}]);
     this.loadMailConfig(true);
   }
 
diff --git a/ui/src/app/configuration/export/data-export-import.component.html b/ui/src/app/configuration/export/data-export-import.component.html
new file mode 100644
index 0000000..44352f4
--- /dev/null
+++ b/ui/src/app/configuration/export/data-export-import.component.html
@@ -0,0 +1,52 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<sp-basic-nav-tabs [spNavigationItems]="tabs" [activeLink]="'export'">
+    <div fxLayout="column" class="page-container-padding">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section title="Export" subtitle="Export application data">
+                <div class="subsection-title">Export assets and all linked resources</div>
+                <div fxLayout="column" *ngFor="let asset of assets">
+                    <mat-checkbox (change)="handleSelectionChange($event, asset._id)"><h4>{{asset.assetName}}</h4></mat-checkbox>
+                </div>
+                <div class="mt-10">
+                    <button mat-button
+                            mat-raised-button
+                            color="accent"
+                            [disabled]="selectedAssets.length === 0"
+                            (click)="openExportDialog()">
+                        <i class="material-icons">cloud_download</i><span>&nbsp;Start export process</span>
+                    </button>
+                </div>
+            </sp-split-section>
+        </div>
+        <mat-divider></mat-divider>
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section title="Import" subtitle="Import application data">
+                <div class="subsection-title">Import from application package</div>
+
+                <div class="mt-10">
+                    <button mat-button mat-raised-button color="accent" (click)="openImportDialog()">
+                        <i class="material-icons">cloud_upload</i><span>&nbsp;Start import process</span>
+                    </button>
+                </div>
+            </sp-split-section>
+        </div>
+    </div>
+</sp-basic-nav-tabs>
+
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/configuration/export/data-export-import.component.scss
similarity index 99%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/configuration/export/data-export-import.component.scss
index 58ba04b..13cbc4a 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/configuration/export/data-export-import.component.scss
@@ -15,4 +15,3 @@
  * limitations under the License.
  *
  */
-
diff --git a/ui/src/app/configuration/export/data-export-import.component.ts b/ui/src/app/configuration/export/data-export-import.component.ts
new file mode 100644
index 0000000..f44891c
--- /dev/null
+++ b/ui/src/app/configuration/export/data-export-import.component.ts
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpConfigurationRoutes } from '../configuration.routes';
+import { SpConfigurationTabs } from '../configuration-tabs';
+import { AssetManagementService, SpAsset } from '@streampipes/platform-services';
+import { MatCheckboxChange } from '@angular/material/checkbox';
+import { SpDataExportDialogComponent } from './export-dialog/data-export-dialog.component';
+import { SpDataImportDialogComponent } from './import-dialog/data-import-dialog.component';
+
+@Component({
+  selector: 'sp-data-export-import',
+  templateUrl: './data-export-import.component.html',
+  styleUrls: ['./data-export-import.component.scss']
+})
+export class SpDataExportImportComponent implements OnInit {
+
+  tabs = SpConfigurationTabs.getTabs();
+
+  assets: SpAsset[];
+  selectedAssets: string[] = [];
+
+  constructor(private breadcrumbService: SpBreadcrumbService,
+              private assetManagementService: AssetManagementService,
+              private dialogService: DialogService) {
+
+  }
+
+  ngOnInit(): void {
+    this.breadcrumbService
+      .updateBreadcrumb([SpConfigurationRoutes.BASE, {label: SpConfigurationTabs.getTabs()[3].itemTitle}]);
+    this.loadAssets();
+  }
+
+  loadAssets(): void {
+    this.assetManagementService
+      .getAllAssets()
+      .subscribe(assets => this.assets = assets.sort((a, b) => a.assetName.localeCompare(b.assetName)));
+  }
+
+  handleSelectionChange(event: MatCheckboxChange,
+                        assetId: string) {
+    if (event.checked) {
+      this.selectedAssets.push(assetId);
+    } else {
+      this.selectedAssets.splice(this.selectedAssets.indexOf(assetId), 1);
+    }
+  }
+
+  openExportDialog(): void {
+    const dialogRef = this.dialogService.open(SpDataExportDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Export resources',
+      width: '50vw',
+      data: {
+        'selectedAssets': this.selectedAssets,
+      }
+    });
+
+    dialogRef.afterClosed().subscribe(() => {
+
+    });
+  }
+
+  openImportDialog(): void {
+    const dialogRef = this.dialogService.open(SpDataImportDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Import resources',
+      width: '50vw',
+      data: {
+      }
+    });
+
+    dialogRef.afterClosed().subscribe(() => {
+
+    });
+  }
+
+}
diff --git a/ui/src/app/configuration/export/data-export.service.ts b/ui/src/app/configuration/export/data-export.service.ts
new file mode 100644
index 0000000..5f3c1d9
--- /dev/null
+++ b/ui/src/app/configuration/export/data-export.service.ts
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { AssetExportConfiguration, PlatformServicesCommons, ExportConfiguration } from '@streampipes/platform-services';
+import { HttpClient, HttpEvent, HttpParams, HttpRequest } from '@angular/common/http';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+
+@Injectable({providedIn: 'root'})
+export class DataExportService {
+
+  constructor(private platformServicesCommons: PlatformServicesCommons,
+              private http: HttpClient) {
+  }
+
+  getExportPreview(assetIds: string[]): Observable<ExportConfiguration> {
+    return this.http.post(this.exportBasePath + '/preview', assetIds)
+      .pipe(map(res => res as ExportConfiguration));
+  }
+
+  triggerExport(exportConfig: ExportConfiguration): Observable<Blob> {
+    return this.http.post(this.exportBasePath + '/download', exportConfig, {responseType: 'blob'});
+  }
+
+  triggerImport(file: File,
+                config: AssetExportConfiguration) {
+    const data: FormData = new FormData();
+    data.append('file_upload', file, file.name);
+    data.append('configuration', new Blob([JSON.stringify(config)], {type: 'application/json'}));
+
+    const params = new HttpParams();
+    const options = {
+      params,
+      reportProgress: true,
+    };
+
+    const req = new HttpRequest('POST', this.importBasePath, data, options);
+    return this.http.request(req);
+  }
+
+  getImportPreview(file: File): Observable<HttpEvent<any>> {
+    const data: FormData = new FormData();
+    data.append('file_upload', file, file.name);
+
+    const params = new HttpParams();
+    const options = {
+      params,
+      reportProgress: true,
+    };
+
+    const req = new HttpRequest('POST', this.importBasePath + '/preview', data, options);
+    return this.http.request(req);
+  }
+
+  private get exportBasePath(): string {
+    return this.platformServicesCommons.apiBasePath + '/export';
+  }
+
+  private get importBasePath(): string {
+    return this.platformServicesCommons.apiBasePath + '/import';
+  }
+
+}
diff --git a/ui/src/app/configuration/export/export-dialog/data-export-dialog.component.html b/ui/src/app/configuration/export/export-dialog/data-export-dialog.component.html
new file mode 100644
index 0000000..3dbfec2
--- /dev/null
+++ b/ui/src/app/configuration/export/export-dialog/data-export-dialog.component.html
@@ -0,0 +1,56 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content">
+        <div fxFlex="100" fxLayout="column" class="p-15" *ngIf="preview && !exportInProgress">
+            <div *ngFor="let config of preview.assetExportConfiguration">
+                <h4>Exported items {{config.assetName}}</h4>
+                <sp-data-export-item [exportItems]="config.adapters" sectionTitle="Adapters"></sp-data-export-item>
+                <sp-data-export-item [exportItems]="config.dashboards" sectionTitle="Dashboards"></sp-data-export-item>
+                <sp-data-export-item [exportItems]="config.dataViews" sectionTitle="Data Views"></sp-data-export-item>
+                <sp-data-export-item [exportItems]="config.dataSources" sectionTitle="Data Sources"></sp-data-export-item>
+                <sp-data-export-item [exportItems]="config.dataLakeMeasures" sectionTitle="Data Lake Storage"></sp-data-export-item>
+                <sp-data-export-item [exportItems]="config.files" sectionTitle="Files"></sp-data-export-item>
+                <sp-data-export-item [exportItems]="config.pipelines" sectionTitle="Pipelines"></sp-data-export-item>
+            </div>
+        </div>
+        <div fxFlex="100" fxLayout="column" *ngIf="exportInProgress" class="mt-10" fxLayoutAlign="center center">
+            <mat-spinner [diameter]="50" color="accent"></mat-spinner>
+            <h4 class="mt-10">Exporting resources...</h4>
+            <h5 class="mt-10">Depending on number and size of exported files, this might take a while...</h5>
+        </div>
+
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <div fxLayout="column">
+            <div fxLayout="row">
+                <button mat-button
+                        mat-raised-button
+                        color="accent"
+                        style="margin-right: 10px;" (click)="generateDownloadPackage()">
+                    <i class="material-icons">file_download</i><span>&nbsp;Download export</span>
+                </button>
+                <button mat-button mat-raised-button class="mat-basic" (click)="close()">
+                    Cancel
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/configuration/export/export-dialog/data-export-dialog.component.scss
similarity index 93%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/configuration/export/export-dialog/data-export-dialog.component.scss
index 58ba04b..fddade7 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/configuration/export/export-dialog/data-export-dialog.component.scss
@@ -16,3 +16,4 @@
  *
  */
 
+@import '../../../../scss/sp/sp-dialog.scss';
diff --git a/ui/src/app/configuration/export/export-dialog/data-export-dialog.component.ts b/ui/src/app/configuration/export/export-dialog/data-export-dialog.component.ts
new file mode 100644
index 0000000..df8d7d8
--- /dev/null
+++ b/ui/src/app/configuration/export/export-dialog/data-export-dialog.component.ts
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import { DialogRef } from '@streampipes/shared-ui';
+import { DataExportService } from '../data-export.service';
+import { ExportConfiguration } from '@streampipes/platform-services';
+
+@Component({
+  selector: 'sp-data-export-dialog',
+  templateUrl: './data-export-dialog.component.html',
+  styleUrls: ['./data-export-dialog.component.scss'],
+})
+export class SpDataExportDialogComponent implements OnInit {
+
+  @Input()
+  selectedAssets: string[];
+
+  preview: ExportConfiguration;
+  exportInProgress = false;
+
+  constructor(private dialogRef: DialogRef<SpDataExportDialogComponent>,
+              private dataExportService: DataExportService) {
+
+  }
+
+  ngOnInit(): void {
+    this.dataExportService.getExportPreview(this.selectedAssets).subscribe(preview => {
+      this.preview = preview;
+    });
+  }
+
+  close(): void {
+    this.dialogRef.close();
+  }
+
+  generateDownloadPackage(): void {
+    this.exportInProgress = true;
+    this.dataExportService.triggerExport(this.preview).subscribe(result => {
+      this.downloadFile(result);
+    });
+  }
+
+  downloadFile(data: any) {
+    const blob = new Blob([data], { type: 'application/zip' });
+    const url = window.URL.createObjectURL(blob);
+    window.open(url);
+    this.dialogRef.close();
+  }
+
+}
diff --git a/ui/src/app/connect/connect.component.html b/ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.html
similarity index 73%
rename from ui/src/app/connect/connect.component.html
rename to ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.html
index 5a97b18..d9879aa 100644
--- a/ui/src/app/connect/connect.component.html
+++ b/ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.html
@@ -1,20 +1,26 @@
-<!--

-  ~ Licensed to the Apache Software Foundation (ASF) under one or more

-  ~ contributor license agreements.  See the NOTICE file distributed with

-  ~ this work for additional information regarding copyright ownership.

-  ~ The ASF licenses this file to You under the Apache License, Version 2.0

-  ~ (the "License"); you may not use this file except in compliance with

-  ~ the License.  You may obtain a copy of the License at

-  ~

-  ~    http://www.apache.org/licenses/LICENSE-2.0

-  ~

-  ~ Unless required by applicable law or agreed to in writing, software

-  ~ distributed under the License is distributed on an "AS IS" BASIS,

-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-  ~ See the License for the specific language governing permissions and

-  ~ limitations under the License.

-  ~

-  -->

-

-<sp-data-marketplace *ngIf="newAdapterFromDescription===undefined" (selectAdapterEmitter)="selectAdapter($event)"></sp-data-marketplace>

-

+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="column" fxFlex="100">
+    <h5>{{sectionTitle}}</h5>
+    <mat-checkbox *ngFor="let exportItem of exportItems; let i = index"
+                  [checked]="exportItem.selected"
+                  (change)="changeItem($event, i)">
+        {{exportItem.label}}
+    </mat-checkbox>
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.scss
similarity index 99%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.scss
index 58ba04b..13cbc4a 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.scss
@@ -15,4 +15,3 @@
  * limitations under the License.
  *
  */
-
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts b/ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.ts
similarity index 63%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
copy to ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.ts
index 4e64c25..1d6e683 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
+++ b/ui/src/app/configuration/export/export-dialog/data-export-item/data-export-item.component.ts
@@ -17,22 +17,29 @@
  */
 
 import { Component, Input, OnInit } from '@angular/core';
-import { Notification } from '@streampipes/platform-services';
+import { ExportItem } from '@streampipes/platform-services';
+import { MatCheckboxChange } from '@angular/material/checkbox';
 
 @Component({
-  selector: 'sp-error-message',
-  templateUrl: './error-message.component.html',
-  styleUrls: ['./error-message.component.scss']
+  selector: 'sp-data-export-item',
+  templateUrl: './data-export-item.component.html',
+  styleUrls: ['./data-export-item.component.scss'],
 })
-export class ErrorMessageComponent implements OnInit {
+export class SpDataExportItemComponent implements OnInit {
 
-  @Input() errorMessages: Notification[];
+  @Input()
+  exportItems: ExportItem[];
 
-  showErrorMessage = false;
-
-  constructor() { }
+  @Input()
+  sectionTitle: string;
 
   ngOnInit(): void {
   }
 
+  changeItem(event: MatCheckboxChange,
+             index: number) {
+    this.exportItems[index].selected = event.checked;
+  }
+
+
 }
diff --git a/ui/src/app/configuration/export/import-dialog/data-import-dialog.component.html b/ui/src/app/configuration/export/import-dialog/data-import-dialog.component.html
new file mode 100644
index 0000000..630b7cb
--- /dev/null
+++ b/ui/src/app/configuration/export/import-dialog/data-import-dialog.component.html
@@ -0,0 +1,106 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content">
+        <div fxFlex="100" fxLayout="column" class="p-15" *ngIf="currentImportStep === 0">
+            <h4>Upload application package file</h4>
+            <mat-form-field style="width: 95%" (click)="fileInput.click();" color="accent">
+                <input matInput placeholder="File" disabled (value)="fileName">
+                <input #fileInput type="file" style="display:none;"
+                       (change)="handleFileInput($event.target.files)">
+                <div>
+                    {{fileName}}
+                    <mat-progress-bar mode="determinate"
+                                      value="{{uploadStatus}}" *ngIf="uploadStatus > 0"
+                                      color="accent">
+                    </mat-progress-bar>
+                </div>
+                <button color="accent"
+                        matSuffix
+                        mat-button
+                        style="min-width: 0px">
+                    <mat-icon *ngIf="uploadStatus < 99">insert_drive_file</mat-icon>
+                    <mat-icon *ngIf="uploadStatus == 100" class="green-icon">check_circle</mat-icon>
+                </button>
+                <mat-error *ngIf="!hasInput">
+                    {{errorMessage}}
+                </mat-error>
+            </mat-form-field>
+        </div>
+        <div fxFlex="100" fxLayout="column" class="p-15" *ngIf="currentImportStep === 1">
+            <h4>Select resources to import</h4>
+            <sp-data-export-item [exportItems]="importConfiguration.assets" sectionTitle="Assets"></sp-data-export-item>
+            <sp-data-export-item [exportItems]="importConfiguration.adapters" sectionTitle="Adapters"></sp-data-export-item>
+            <sp-data-export-item [exportItems]="importConfiguration.dashboards" sectionTitle="Dashboards"></sp-data-export-item>
+            <sp-data-export-item [exportItems]="importConfiguration.dataViews" sectionTitle="Data Views"></sp-data-export-item>
+            <sp-data-export-item [exportItems]="importConfiguration.dataSources" sectionTitle="Data Sources"></sp-data-export-item>
+            <sp-data-export-item [exportItems]="importConfiguration.dataLakeMeasures" sectionTitle="Data Lake Storage"></sp-data-export-item>
+            <sp-data-export-item [exportItems]="importConfiguration.files" sectionTitle="Files"></sp-data-export-item>
+            <sp-data-export-item [exportItems]="importConfiguration.pipelines" sectionTitle="Pipelines"></sp-data-export-item>
+
+            <div fxFlex="100" fxLayout="column" *ngIf="currentImportStep === 1" class="mt-10">
+                <h4>Import options</h4>
+                <div fxLayout="column"*ngIf="importConfiguration">
+                    <mat-checkbox [(ngModel)]="importConfiguration.overrideBrokerSettings">Use broker settings from this instance</mat-checkbox>
+                </div>
+            </div>
+        </div>
+        <div fxFlex="100" fxLayout="column" *ngIf="currentImportStep === 2" class="mt-10" fxLayoutAlign="center center">
+            <mat-spinner [diameter]="50" color="accent"></mat-spinner>
+            <h4 class="mt-10">Importing resources...</h4>
+        </div>
+
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <div fxLayout="column">
+            <div fxLayout="row">
+                <button mat-button
+                        mat-raised-button
+                        color="accent"
+                        style="margin-right: 10px;" (click)="performPreview()"
+                        *ngIf="currentImportStep === 0"
+                        [disabled]="!hasInput">
+                    <span>&nbsp;Next</span>
+                </button>
+                <button mat-button
+                        mat-raised-button
+                        color="accent"
+                        style="margin-right: 10px;"
+                        *ngIf="currentImportStep === 1" (click)="performImport()">
+                    <i class="material-icons">file_download</i><span>&nbsp;Import data</span>
+                </button>
+                <button mat-button
+                        mat-raised-button
+                        class="mat-basic"
+                        style="margin-right: 10px;"
+                        (click)="back()" *ngIf="currentImportStep > 0">
+                    Back
+                </button>
+                <button mat-button
+                        mat-raised-button
+                        class="mat-basic"
+                        (click)="close()">
+                    Cancel
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
+
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/configuration/export/import-dialog/data-import-dialog.component.scss
similarity index 93%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/configuration/export/import-dialog/data-import-dialog.component.scss
index 58ba04b..fddade7 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/configuration/export/import-dialog/data-import-dialog.component.scss
@@ -16,3 +16,4 @@
  *
  */
 
+@import '../../../../scss/sp/sp-dialog.scss';
diff --git a/ui/src/app/configuration/export/import-dialog/data-import-dialog.component.ts b/ui/src/app/configuration/export/import-dialog/data-import-dialog.component.ts
new file mode 100644
index 0000000..ea40c28
--- /dev/null
+++ b/ui/src/app/configuration/export/import-dialog/data-import-dialog.component.ts
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { DialogRef } from '@streampipes/shared-ui';
+import { DataExportService } from '../data-export.service';
+import { HttpEventType, HttpResponse } from '@angular/common/http';
+import { AssetExportConfiguration } from '../../../../../dist/streampipes/platform-services';
+
+@Component({
+  selector: 'sp-data-import-dialog',
+  templateUrl: './data-import-dialog.component.html',
+  styleUrls: ['./data-import-dialog.component.scss'],
+})
+export class SpDataImportDialogComponent implements OnInit {
+
+  currentImportStep = 0;
+
+  inputValue: string;
+  fileName: string;
+
+  selectedUploadFile: File;
+  importConfiguration: AssetExportConfiguration;
+
+  hasInput = false;
+  errorMessage = 'Please enter a value';
+
+  uploadStatus = 0;
+
+  constructor(private dialogRef: DialogRef<SpDataImportDialogComponent>,
+              private dataExportService: DataExportService) {
+
+  }
+
+  ngOnInit(): void {
+  }
+
+  handleFileInput(files: any) {
+    this.hasInput = true;
+    this.selectedUploadFile = files[0];
+    this.fileName = this.selectedUploadFile.name;
+    this.uploadStatus = 0;
+  }
+
+  performPreview(): void {
+    this.uploadStatus = 0;
+    if (this.selectedUploadFile !== undefined) {
+      this.dataExportService.getImportPreview(this.selectedUploadFile).subscribe(
+        event => {
+          if (event.type === HttpEventType.UploadProgress) {
+            this.uploadStatus = Math.round(100 * event.loaded / event.total);
+          } else if (event instanceof HttpResponse) {
+           this.importConfiguration = event.body as AssetExportConfiguration;
+           this.importConfiguration.overrideBrokerSettings = true;
+           this.currentImportStep++;
+          }
+        },
+        error => {
+        },
+      );
+    }
+  }
+
+  performImport(): void {
+    this.currentImportStep = 2;
+    this.dataExportService.triggerImport(this.selectedUploadFile, this.importConfiguration).subscribe(result => {
+      this.dialogRef.close();
+    });
+  }
+
+  back(): void {
+    this.currentImportStep--;
+  }
+
+  close(): void {
+    this.dialogRef.close();
+  }
+
+
+}
diff --git a/ui/src/app/configuration/general-configuration/general-configuration.component.html b/ui/src/app/configuration/general-configuration/general-configuration.component.html
index 2df1134..b6cfae4 100644
--- a/ui/src/app/configuration/general-configuration/general-configuration.component.html
+++ b/ui/src/app/configuration/general-configuration/general-configuration.component.html
@@ -15,84 +15,78 @@
   ~ limitations under the License.
   ~
   -->
-
-<div fxLayout="column" class="page-container-padding">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" *ngIf="formReady">
-        <form [formGroup]="parentForm" fxFlex="100" fxLayout="column">
-            <div class="warning mb-10" *ngIf="!generalConfig.configured">These are default values - to use features
-                such as email you need to store these values once.
-            </div>
-            <sp-split-section title="Basic"
-                              subtitle="Basic settings">
-                <div class="subsection-title">App Name</div>
-                <mat-form-field color="accent" class="ml-10">
-                    <mat-label>App Name</mat-label>
-                    <input formControlName="appName" fxFlex
-                           matInput
-                           required>
-                </mat-form-field>
-                <div class="subsection-title">Host and Port</div>
-                <div fxLayout="column" fxFlex="100">
-                    <div fxLayout="row">
-                        <div>
-                            <mat-button-toggle-group name="protocol" aria-label="Protocol" formControlName="protocol">
-                                <mat-button-toggle value="http">http</mat-button-toggle>
-                                <mat-button-toggle value="https">https</mat-button-toggle>
-                            </mat-button-toggle-group>
+<sp-basic-nav-tabs [spNavigationItems]="tabs" [activeLink]="'general'">
+    <div fxLayout="column" class="page-container-padding">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" *ngIf="formReady">
+            <form [formGroup]="parentForm" fxFlex="100" fxLayout="column">
+                <div class="warning mb-10" *ngIf="!generalConfig.configured">These are default values - to use features
+                    such as email you need to store these values once.
+                </div>
+                <sp-split-section title="Basic" subtitle="Basic settings">
+                    <div class="subsection-title">App Name</div>
+                    <mat-form-field color="accent" class="ml-10">
+                        <mat-label>App Name</mat-label>
+                        <input formControlName="appName" fxFlex matInput required>
+                    </mat-form-field>
+                    <div class="subsection-title">Host and Port</div>
+                    <div fxLayout="column" fxFlex="100">
+                        <div fxLayout="row">
+                            <div fxLayout="row" fxLayoutAlign="start center">
+                                <mat-button-toggle-group name="protocol" aria-label="Protocol"
+                                    formControlName="protocol">
+                                    <mat-button-toggle value="http">http</mat-button-toggle>
+                                    <mat-button-toggle value="https">https</mat-button-toggle>
+                                </mat-button-toggle-group>
+                            </div>
+                            <mat-form-field color="accent" class="ml-10">
+                                <mat-label>Host</mat-label>
+                                <input formControlName="hostname" fxFlex matInput required>
+                            </mat-form-field>
+                            <mat-form-field color="accent" class="ml-10">
+                                <mat-label>Port</mat-label>
+                                <input formControlName="port" fxFlex matInput type="number" required>
+                            </mat-form-field>
                         </div>
-                        <mat-form-field color="accent" class="ml-10">
-                            <mat-label>Host</mat-label>
-                            <input formControlName="hostname" fxFlex
-                                   matInput
-                                   required>
-                        </mat-form-field>
-                        <mat-form-field color="accent" class="ml-10">
-                            <mat-label>Port</mat-label>
-                            <input formControlName="port" fxFlex
-                                   matInput
-                                   type="number"
-                                   required>
-                        </mat-form-field>
                     </div>
-                </div>
-                <div class="mt-10">
-                    <button mat-button mat-raised-button color="accent" (click)="updateConfig()"
-                            style="margin-right:10px;"
-                            [disabled]="!parentForm.valid"
+                    <div class="mt-10">
+                        <button mat-button mat-raised-button color="accent" (click)="updateConfig()"
+                            style="margin-right:10px;" [disabled]="!parentForm.valid"
                             data-cy="sp-element-general-config-save">
-                        <i class="material-icons">save</i><span>&nbsp;Save</span>
-                    </button>
-                </div>
-            </sp-split-section>
-            <mat-divider></mat-divider>
-            <sp-split-section title="Registration"
-                              subtitle="Registration process">
-                <div class="warning mb-10" *ngIf="!generalConfig.configured || !mailConfig.emailConfigured">Requires valid
-                    mail server settings and basic host settings.
-                </div>
-                <mat-checkbox [disabled]="!generalConfig.configured || !mailConfig.emailConfigured"
-                              formControlName="allowSelfRegistration">Allow self-registration
-                </mat-checkbox>
-                <div *ngIf="generalConfig.allowSelfRegistration" class="mt-10 mb-10">
-                    <h5>Default roles for new users</h5>
-                    <mat-select formControlName="defaultUserRoles" [multiple]="true">
-                        <mat-option *ngFor="let role of availableRoles" [value]="role.role">{{role.roleTitle}}</mat-option>
-                    </mat-select>
-                </div>
-                <mat-checkbox [disabled]="!generalConfig.configured || !mailConfig.emailConfigured"
-                              formControlName="allowPasswordRecovery">Allow self-service password recovery
-                </mat-checkbox>
+                            <i class="material-icons">save</i><span>&nbsp;Save</span>
+                        </button>
+                    </div>
+                </sp-split-section>
+                <mat-divider></mat-divider>
+                <sp-split-section title="Registration" subtitle="Registration process">
+                    <div class="warning mb-10" *ngIf="!generalConfig.configured || !mailConfig.emailConfigured">Requires
+                        valid
+                        mail server settings and basic host settings.
+                    </div>
+                    <mat-checkbox [disabled]="!generalConfig.configured || !mailConfig.emailConfigured"
+                        formControlName="allowSelfRegistration">Allow self-registration
+                    </mat-checkbox>
+                    <div *ngIf="generalConfig.allowSelfRegistration" class="mt-10 mb-10">
+                        <h5>Default roles for new users</h5>
+                        <mat-select formControlName="defaultUserRoles" [multiple]="true">
+                            <mat-option *ngFor="let role of availableRoles" [value]="role.role">{{role.roleTitle}}
+                            </mat-option>
+                        </mat-select>
+                    </div>
+                    <mat-checkbox [disabled]="!generalConfig.configured || !mailConfig.emailConfigured"
+                        formControlName="allowPasswordRecovery">Allow self-service password recovery
+                    </mat-checkbox>
 
-                <div class="mt-10">
-                    <button mat-button mat-raised-button color="accent" (click)="updateConfig()"
+                    <div class="mt-10">
+                        <button mat-button mat-raised-button color="accent" (click)="updateConfig()"
                             style="margin-right:10px;"
                             [disabled]="!generalConfig.configured || !mailConfig.emailConfigured"
                             data-cy="sp-element-general-registration-config-save">
-                        <i class="material-icons">save</i><span>&nbsp;Save</span>
-                    </button>
-                </div>
-            </sp-split-section>
-        </form>
-    </div>
+                            <i class="material-icons">save</i><span>&nbsp;Save</span>
+                        </button>
+                    </div>
+                </sp-split-section>
+            </form>
+        </div>
 
-</div>
+    </div>
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/configuration/general-configuration/general-configuration.component.ts b/ui/src/app/configuration/general-configuration/general-configuration.component.ts
index 7c3a787..a2a5536 100644
--- a/ui/src/app/configuration/general-configuration/general-configuration.component.ts
+++ b/ui/src/app/configuration/general-configuration/general-configuration.component.ts
@@ -18,12 +18,20 @@
 
 import { Component, OnInit } from '@angular/core';
 import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
-import { GeneralConfigService, GeneralConfigModel, MailConfigService, EmailConfig } from '@streampipes/platform-services';
+import {
+  EmailConfig,
+  GeneralConfigModel,
+  GeneralConfigService,
+  MailConfigService
+} from '@streampipes/platform-services';
 import { zip } from 'rxjs';
 import { AvailableRolesService } from '../../services/available-roles.service';
 import { RoleDescription } from '../../_models/auth.model';
 import { UserRole } from '../../_enums/user-role.enum';
 import { AppConstants } from '../../services/app.constants';
+import { SpConfigurationTabs } from '../configuration-tabs';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpConfigurationRoutes } from '../configuration.routes';
 
 @Component({
   selector: 'sp-general-configuration',
@@ -32,6 +40,8 @@
 })
 export class GeneralConfigurationComponent implements OnInit {
 
+  tabs = SpConfigurationTabs.getTabs();
+
   parentForm: FormGroup;
   formReady = false;
 
@@ -44,9 +54,11 @@
               private generalConfigService: GeneralConfigService,
               private mailConfigService: MailConfigService,
               private availableRolesService: AvailableRolesService,
-              private appConstants: AppConstants) {}
+              private appConstants: AppConstants,
+              private breadcrumbService: SpBreadcrumbService) {}
 
   ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb([SpConfigurationRoutes.BASE, {label: SpConfigurationTabs.getTabs()[0].itemTitle}]);
     this.availableRoles = this.availableRolesService.availableRoles.filter(role => role.role !== UserRole.ROLE_ADMIN);
     zip(this.generalConfigService.getGeneralConfig(), this.mailConfigService.getMailConfig()).subscribe(configs => {
       if (configs[0].configured) {
diff --git a/ui/src/app/configuration/messaging-configuration/messaging-configuration.component.html b/ui/src/app/configuration/messaging-configuration/messaging-configuration.component.html
index 61d96e3..ed44cf6 100644
--- a/ui/src/app/configuration/messaging-configuration/messaging-configuration.component.html
+++ b/ui/src/app/configuration/messaging-configuration/messaging-configuration.component.html
@@ -16,78 +16,71 @@
   ~
   -->
 
-<div fxLayout="column" class="page-container-padding">
-    <sp-split-section title="Kafka Settings"
-                      subtitle="Manage Kafka settings for pipeline communication">
-        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="page-container-padding-inner">
-            <form (ngSubmit)="updateMessagingSettings()" class="form-width" fxFlex="100" fxLayout="column"
-                  *ngIf="loadingCompleted">
-                <mat-form-field class="form-field" fxFlex="100">
-                    <input matInput [(ngModel)]="messagingSettings.batchSize"
-                           [placeholder]="'Batch Size'" type="text"
-                           [ngModelOptions]="{standalone: true}">
-                </mat-form-field>
-                <mat-form-field class="form-field" fxFlex="100">
-                    <input matInput [(ngModel)]="messagingSettings.messageMaxBytes"
-                           [placeholder]="'Message Max Bytes'" type="text"
-                           [ngModelOptions]="{standalone: true}">
-                </mat-form-field>
-                <mat-form-field class="form-field" fxFlex="100">
-                    <input matInput [(ngModel)]="messagingSettings.acks"
-                           [placeholder]="'Acks'" type="text"
-                           [ngModelOptions]="{standalone: true}">
-                </mat-form-field>
-                <mat-form-field class="form-field" fxFlex="100">
-                    <input matInput [(ngModel)]="messagingSettings.lingerMs"
-                           [placeholder]="'Linger MS'" type="text"
-                           [ngModelOptions]="{standalone: true}">
-                </mat-form-field>
-                <div fxLayoutAlign="start center" class="mt-10">
-                    <button mat-raised-button color="accent" type="submit"
+<sp-basic-nav-tabs [spNavigationItems]="tabs" [activeLink]="'messaging'">
+    <div fxLayout="column" class="page-container-padding">
+        <sp-split-section title="Kafka Settings" subtitle="Manage Kafka settings for pipeline communication">
+            <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="page-container-padding-inner">
+                <form (ngSubmit)="updateMessagingSettings()" class="form-width" fxFlex="100" fxLayout="column"
+                    *ngIf="loadingCompleted">
+                    <mat-form-field class="form-field" fxFlex="100">
+                        <input matInput [(ngModel)]="messagingSettings.batchSize" [placeholder]="'Batch Size'"
+                            type="text" [ngModelOptions]="{standalone: true}">
+                    </mat-form-field>
+                    <mat-form-field class="form-field" fxFlex="100">
+                        <input matInput [(ngModel)]="messagingSettings.messageMaxBytes"
+                            [placeholder]="'Message Max Bytes'" type="text" [ngModelOptions]="{standalone: true}">
+                    </mat-form-field>
+                    <mat-form-field class="form-field" fxFlex="100">
+                        <input matInput [(ngModel)]="messagingSettings.acks" [placeholder]="'Acks'" type="text"
+                            [ngModelOptions]="{standalone: true}">
+                    </mat-form-field>
+                    <mat-form-field class="form-field" fxFlex="100">
+                        <input matInput [(ngModel)]="messagingSettings.lingerMs" [placeholder]="'Linger MS'" type="text"
+                            [ngModelOptions]="{standalone: true}">
+                    </mat-form-field>
+                    <div fxLayoutAlign="start center" class="mt-10">
+                        <button mat-raised-button color="accent" type="submit"
                             class="md-raised md-primary submit-button">Update
+                        </button>
+                    </div>
+
+                </form>
+            </div>
+        </sp-split-section>
+        <mat-divider></mat-divider>
+
+        <sp-split-section title="Message Formats" subtitle="Manage the priority of message formats used">
+            <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="page-container-padding-inner">
+                <div cdkDropList class="data-format-list" (cdkDropListDropped)="drop($event)" *ngIf="loadingCompleted">
+                    <div class="data-format-box" *ngFor="let format of messagingSettings.prioritizedFormats" cdkDrag>
+                        {{format}}
+                    </div>
+                </div>
+                <div fxLayoutAlign="start center" class="mt-10">
+                    <button mat-raised-button color="accent" type="submit" class="md-raised md-primary submit-button"
+                        (click)="updateMessagingSettings()">Update
                     </button>
                 </div>
+            </div>
+        </sp-split-section>
 
-            </form>
-        </div>
-    </sp-split-section>
-    <mat-divider></mat-divider>
+        <mat-divider></mat-divider>
 
-    <sp-split-section title="Message Formats"
-                      subtitle="Manage the priority of message formats used">
-        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="page-container-padding-inner">
-            <div cdkDropList class="data-format-list" (cdkDropListDropped)="drop($event)"
-                 *ngIf="loadingCompleted">
-                <div class="data-format-box" *ngFor="let format of messagingSettings.prioritizedFormats"
-                     cdkDrag>
-                    {{format}}
+        <sp-split-section title="Protocols" subtitle="Manage the priority of protocols used">
+            <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="page-container-padding-inner">
+                <div cdkDropList class="data-format-list" (cdkDropListDropped)="dropProtocol($event)"
+                    *ngIf="loadingCompleted">
+                    <div class="data-format-box" *ngFor="let protocol of messagingSettings.prioritizedProtocols"
+                        cdkDrag>
+                        {{protocol}}
+                    </div>
+                </div>
+                <div fxLayoutAlign="start center" class="mt-10">
+                    <button mat-raised-button color="accent" type="submit" class="md-raised md-primary submit-button"
+                        (click)="updateMessagingSettings()">Update
+                    </button>
                 </div>
             </div>
-            <div fxLayoutAlign="start center" class="mt-10">
-                <button mat-raised-button color="accent" type="submit"
-                        class="md-raised md-primary submit-button" (click)="updateMessagingSettings()">Update
-                </button>
-            </div>
-        </div>
-    </sp-split-section>
-
-    <mat-divider></mat-divider>
-
-    <sp-split-section title="Protocols"
-                      subtitle="Manage the priority of protocols used">
-        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="page-container-padding-inner">
-            <div cdkDropList class="data-format-list" (cdkDropListDropped)="dropProtocol($event)"
-                 *ngIf="loadingCompleted">
-                <div class="data-format-box" *ngFor="let protocol of messagingSettings.prioritizedProtocols"
-                     cdkDrag>
-                    {{protocol}}
-                </div>
-            </div>
-            <div fxLayoutAlign="start center" class="mt-10">
-                <button mat-raised-button color="accent" type="submit"
-                        class="md-raised md-primary submit-button" (click)="updateMessagingSettings()">Update
-                </button>
-            </div>
-        </div>
-    </sp-split-section>
-</div>
+        </sp-split-section>
+    </div>
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/configuration/messaging-configuration/messaging-configuration.component.ts b/ui/src/app/configuration/messaging-configuration/messaging-configuration.component.ts
index 51a79ed..4d972b3 100644
--- a/ui/src/app/configuration/messaging-configuration/messaging-configuration.component.ts
+++ b/ui/src/app/configuration/messaging-configuration/messaging-configuration.component.ts
@@ -20,6 +20,9 @@
 import { ConfigurationService } from '../shared/configuration.service';
 import { MessagingSettings } from '../shared/messaging-settings.model';
 import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
+import { SpConfigurationTabs } from '../configuration-tabs';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpConfigurationRoutes } from '../configuration.routes';
 
 @Component({
     selector: 'messaging-configuration',
@@ -28,14 +31,18 @@
 })
 export class MessagingConfigurationComponent implements OnInit {
 
+    tabs = SpConfigurationTabs.getTabs();
+
     messagingSettings: MessagingSettings;
     loadingCompleted = false;
 
-    constructor(private configurationService: ConfigurationService) {
+    constructor(private configurationService: ConfigurationService,
+                private breadcrumbService: SpBreadcrumbService) {
 
     }
 
     ngOnInit() {
+        this.breadcrumbService.updateBreadcrumb([SpConfigurationRoutes.BASE, {label: SpConfigurationTabs.getTabs()[4].itemTitle}]);
         this.getMessagingSettings();
     }
 
diff --git a/ui/src/app/configuration/pipeline-element-configuration/pipeline-element-configuration.component.html b/ui/src/app/configuration/pipeline-element-configuration/pipeline-element-configuration.component.html
index 339fe0a..e7caaa0 100644
--- a/ui/src/app/configuration/pipeline-element-configuration/pipeline-element-configuration.component.html
+++ b/ui/src/app/configuration/pipeline-element-configuration/pipeline-element-configuration.component.html
@@ -16,60 +16,63 @@
   ~
   -->
 
-<div fxLayout="row" class="page-container-padding">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
-        <sp-split-section title="Pipeline Element Configuration"
-                          subtitle="Configure basic settings of core and extensions services">
-            <table fxFlex="100" mat-table [dataSource]="dataSource" multiTemplateDataRows>
+<sp-basic-nav-tabs [spNavigationItems]="tabs" [activeLink]="'pipelineelement'">
+    <div fxLayout="row" class="page-container-padding">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section title="Pipeline Element Configuration"
+                subtitle="Configure basic settings of core and extensions services">
+                <table fxFlex="100" mat-table [dataSource]="dataSource" multiTemplateDataRows>
 
-                <ng-container matColumnDef="status">
-                    <th fxFlex="30" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Status</th>
-                    <td fxFlex="30" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+                    <ng-container matColumnDef="status">
+                        <th fxFlex="30" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Status</th>
+                        <td fxFlex="30" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
                             <span *ngIf="element.meta.status === 'passing'" fxLayoutAlign="center center">
                                 <mat-icon class="service-icon-passing">lens</mat-icon>
                             </span>
-                        <span *ngIf="element.meta.status === 'critical'" fxLayoutAlign="center center">
+                            <span *ngIf="element.meta.status === 'critical'" fxLayoutAlign="center center">
                                 <mat-icon class="service-icon-critical">lens</mat-icon>
                             </span>
-                    </td>
-                </ng-container>
+                        </td>
+                    </ng-container>
 
-                <ng-container matColumnDef="name">
-                    <th fxFlex="40" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Extensions Service Group
-                    </th>
-                    <td fxFlex="40" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
-                        {{element.name}}
-                    </td>
-                </ng-container>
+                    <ng-container matColumnDef="name">
+                        <th fxFlex="40" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Extensions
+                            Service Group
+                        </th>
+                        <td fxFlex="40" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+                            {{element.name}}
+                        </td>
+                    </ng-container>
 
-                <ng-container matColumnDef="action">
-                    <th fxFlex="30" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Action</th>
-                    <td fxFlex="30" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
-                        <button mat-button mat-raised-button color="accent" (click)="expand(element)">
-                            Edit
-                        </button>
-                    </td>
-                </ng-container>
+                    <ng-container matColumnDef="action">
+                        <th fxFlex="30" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Action</th>
+                        <td fxFlex="30" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+                            <button mat-button mat-raised-button color="accent" (click)="expand(element)">
+                                Edit
+                            </button>
+                        </td>
+                    </ng-container>
 
-                <ng-container matColumnDef="expandedDetail">
-                    <td mat-cell *matCellDef="let element" [attr.colspan]="displayedColumns.length">
-                        <div class="consul-configuration-detail"
-                             [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
-                            <div fxFlex="100">
-                                <consul-configs [consulService]="element"
-                                                (updateConsulService)="updateConsulService($event)"></consul-configs>
+                    <ng-container matColumnDef="expandedDetail">
+                        <td mat-cell *matCellDef="let element" [attr.colspan]="displayedColumns.length">
+                            <div class="consul-configuration-detail"
+                                [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
+                                <div fxFlex="100">
+                                    <consul-configs [consulService]="element"
+                                        (updateConsulService)="updateConsulService($event)"></consul-configs>
+                                </div>
                             </div>
-                        </div>
-                    </td>
-                </ng-container>
+                        </td>
+                    </ng-container>
 
-                <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
-                <tr mat-row *matRowDef="let element; columns: displayedColumns;"
-                    class="consul-configuration-row"
-                    [class.consul-configuration-row-expanded]="expandedElement === element">
-                </tr>
-                <tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="consul-configuration-detail-row"></tr>
-            </table>
-        </sp-split-section>
+                    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                    <tr mat-row *matRowDef="let element; columns: displayedColumns;" class="consul-configuration-row"
+                        [class.consul-configuration-row-expanded]="expandedElement === element">
+                    </tr>
+                    <tr mat-row *matRowDef="let row; columns: ['expandedDetail']"
+                        class="consul-configuration-detail-row"></tr>
+                </table>
+            </sp-split-section>
+        </div>
     </div>
-</div>
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/configuration/pipeline-element-configuration/pipeline-element-configuration.component.ts b/ui/src/app/configuration/pipeline-element-configuration/pipeline-element-configuration.component.ts
index 56e2ff3..0d28979 100644
--- a/ui/src/app/configuration/pipeline-element-configuration/pipeline-element-configuration.component.ts
+++ b/ui/src/app/configuration/pipeline-element-configuration/pipeline-element-configuration.component.ts
@@ -16,92 +16,104 @@
  *
  */
 
-import { Component, ViewChild } from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
 import { animate, state, style, transition, trigger } from '@angular/animations';
 import { ConfigurationService } from '../shared/configuration.service';
 import { StreampipesPeContainer } from '../shared/streampipes-pe-container.model';
 import { StreampipesPeContainerConifgs } from '../shared/streampipes-pe-container-configs';
 import { MatPaginator } from '@angular/material/paginator';
 import { MatTableDataSource } from '@angular/material/table';
+import { SpConfigurationTabs } from '../configuration-tabs';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpConfigurationRoutes } from '../configuration.routes';
 
 @Component({
-    selector: 'pipeline-element-configuration',
-    templateUrl: './pipeline-element-configuration.component.html',
-    styleUrls: ['./pipeline-element-configuration.component.css'],
-    animations: [
-        trigger('detailExpand', [
-            state('collapsed', style({height: '0px', minHeight: '0', display: 'none'})),
-            state('expanded', style({height: '*'})),
-            transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
-        ]),
-    ]
+  selector: 'pipeline-element-configuration',
+  templateUrl: './pipeline-element-configuration.component.html',
+  styleUrls: ['./pipeline-element-configuration.component.css'],
+  animations: [
+    trigger('detailExpand', [
+      state('collapsed', style({height: '0px', minHeight: '0', display: 'none'})),
+      state('expanded', style({height: '*'})),
+      transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
+    ]),
+  ]
 })
-export class PipelineElementConfigurationComponent {
+export class PipelineElementConfigurationComponent implements OnInit {
 
-    consulServices: StreampipesPeContainer[];
+  tabs = SpConfigurationTabs.getTabs();
 
-    displayedColumns: string[] = ['status', 'name', 'action'];
-    @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;
-    dataSource = new MatTableDataSource<StreampipesPeContainer>();
+  consulServices: StreampipesPeContainer[];
 
-    expandedElement: any;
+  displayedColumns: string[] = ['status', 'name', 'action'];
+  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
+  dataSource = new MatTableDataSource<StreampipesPeContainer>();
 
-    selectedConsulService: StreampipesPeContainer;
-    consulServiceSelected = false;
+  expandedElement: any;
 
-    constructor(private configurationService: ConfigurationService) {
-        this.getConsulServices();
+  selectedConsulService: StreampipesPeContainer;
+  consulServiceSelected = false;
+
+  constructor(private configurationService: ConfigurationService,
+              private breadcrumbService: SpBreadcrumbService) {
+    this.getConsulServices();
+  }
+
+  ngOnInit() {
+    this.breadcrumbService.updateBreadcrumb([SpConfigurationRoutes.BASE, {label: SpConfigurationTabs.getTabs()[5].itemTitle}]);
+  }
+
+  getConsulServices(): void {
+    this.configurationService.getConsulServices()
+      .subscribe(response => {
+        const sortedServices = this.sort(response);
+        this.consulServices = sortedServices;
+        this.dataSource.data = sortedServices;
+      }, error => {
+        console.error(error);
+      });
+  }
+
+  sort(consulServices: StreampipesPeContainer[]): StreampipesPeContainer[] {
+    if (!consulServices || consulServices.length === 0) {
+      return null;
     }
 
-    getConsulServices(): void {
-        this.configurationService.getConsulServices()
-            .subscribe( response => {
-                const sortedServices = this.sort(response);
-                this.consulServices = sortedServices;
-                this.dataSource.data = sortedServices;
-            }, error => {
-                console.error(error);
-            });
+    consulServices.sort((a: StreampipesPeContainer, b: StreampipesPeContainer) => {
+      if (a.name < b.name) {
+        return -1;
+      } else if (a.name > b.name) {
+        return 1;
+      } else {
+        return 0;
+      }
+    });
+    consulServices.forEach(cs => cs.configs.sort((a: StreampipesPeContainerConifgs, b: StreampipesPeContainerConifgs) => {
+      if (a.key < b.key) {
+        return -1;
+      } else if (a.key > b.key) {
+        return 1;
+      } else {
+        return 0;
+      }
+    }));
+    return consulServices;
+  }
+
+  updateConsulService(consulService: StreampipesPeContainer): void {
+    this.configurationService.updateConsulService(consulService)
+      .subscribe(response => {
+
+      }, error => {
+        console.error(error);
+      });
+  }
+
+  expand(element: StreampipesPeContainer) {
+    if (this.expandedElement === element) {
+      this.expandedElement = undefined;
+    } else {
+      this.expandedElement = element;
     }
-
-    sort(consulServices: StreampipesPeContainer[]): StreampipesPeContainer[] {
-        if (!consulServices || consulServices.length === 0) { return null; }
-
-        consulServices.sort((a: StreampipesPeContainer, b: StreampipesPeContainer) => {
-            if (a.name < b.name) {
-                return -1;
-            } else if (a.name > b.name) {
-                return 1;
-            } else {
-                return 0;
-            }
-        });
-        consulServices.forEach(cs => cs.configs.sort((a: StreampipesPeContainerConifgs, b: StreampipesPeContainerConifgs) => {
-            if (a.key < b.key) {
-                return -1;
-            } else if (a.key > b.key) {
-                return 1;
-            } else {
-                return 0;
-            }
-        }));
-        return consulServices;
-    }
-
-    updateConsulService(consulService: StreampipesPeContainer): void {
-        this.configurationService.updateConsulService(consulService)
-            .subscribe(response => {
-
-            }, error => {
-                console.error(error);
-            });
-    }
-
-    expand(element: StreampipesPeContainer) {
-        if (this.expandedElement === element) {
-            this.expandedElement = undefined;
-        } else {
-            this.expandedElement = element;
-        }
-    }
+  }
 }
diff --git a/ui/src/app/configuration/security-configuration/security-configuration.component.html b/ui/src/app/configuration/security-configuration/security-configuration.component.html
index 3afffc9..837e841 100644
--- a/ui/src/app/configuration/security-configuration/security-configuration.component.html
+++ b/ui/src/app/configuration/security-configuration/security-configuration.component.html
@@ -16,36 +16,34 @@
   ~
   -->
 
-<div fxLayout="column" class="page-container-padding">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
-        <sp-split-section title="User Accounts"
-                          subtitle="Add and edit user accounts">
-            <div class="subsection-title">Existing user accounts</div>
-            <sp-security-user-config></sp-security-user-config>
-        </sp-split-section>
+<sp-basic-nav-tabs [spNavigationItems]="tabs" [activeLink]="'security'">
+    <div fxLayout="column" class="page-container-padding">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section title="User Accounts" subtitle="Add and edit user accounts">
+                <div class="subsection-title">Existing user accounts</div>
+                <sp-security-user-config></sp-security-user-config>
+            </sp-split-section>
+        </div>
+        <mat-divider></mat-divider>
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section title="Service Accounts" subtitle="Add and edit service accounts">
+                <div class="subsection-title">Existing service accounts</div>
+                <sp-security-service-config></sp-security-service-config>
+            </sp-split-section>
+        </div>
+        <mat-divider></mat-divider>
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section title="Groups" subtitle="Manage user groups">
+                <div class="subsection-title">Existing groups</div>
+                <sp-security-user-group-config></sp-security-user-group-config>
+            </sp-split-section>
+        </div>
+        <mat-divider></mat-divider>
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section title="Authentication" subtitle="Auth & token settings">
+                <div class="subsection-title">JWT Signature</div>
+                <sp-authentication-configuration></sp-authentication-configuration>
+            </sp-split-section>
+        </div>
     </div>
-    <mat-divider></mat-divider>
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
-        <sp-split-section title="Service Accounts"
-                          subtitle="Add and edit service accounts">
-            <div class="subsection-title">Existing service accounts</div>
-            <sp-security-service-config></sp-security-service-config>
-        </sp-split-section>
-    </div>
-    <mat-divider></mat-divider>
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
-        <sp-split-section title="Groups"
-                          subtitle="Manage user groups">
-            <div class="subsection-title">Existing groups</div>
-            <sp-security-user-group-config></sp-security-user-group-config>
-        </sp-split-section>
-    </div>
-    <mat-divider></mat-divider>
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
-        <sp-split-section title="Authentication"
-                          subtitle="Auth & token settings">
-            <div class="subsection-title">JWT Signature</div>
-            <sp-authentication-configuration></sp-authentication-configuration>
-        </sp-split-section>
-    </div>
-</div>
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/configuration/security-configuration/security-configuration.component.ts b/ui/src/app/configuration/security-configuration/security-configuration.component.ts
index 427c982..ca30cba 100644
--- a/ui/src/app/configuration/security-configuration/security-configuration.component.ts
+++ b/ui/src/app/configuration/security-configuration/security-configuration.component.ts
@@ -17,6 +17,9 @@
  */
 
 import { Component, OnInit } from '@angular/core';
+import { SpConfigurationTabs } from '../configuration-tabs';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpConfigurationRoutes } from '../configuration.routes';
 
 @Component({
   selector: 'sp-security-configuration',
@@ -25,9 +28,12 @@
 })
 export class SecurityConfigurationComponent implements OnInit {
 
-  constructor() {}
+  tabs = SpConfigurationTabs.getTabs();
+
+  constructor(private breadcrumbService: SpBreadcrumbService) {}
 
   ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb([SpConfigurationRoutes.BASE, {label: SpConfigurationTabs.getTabs()[6].itemTitle}]);
   }
 
 }
diff --git a/ui/src/app/connect/components/configuration-group/configuration-group.component.html b/ui/src/app/connect/components/configuration-group/configuration-group.component.html
index 2857534..04e5b2b 100644
--- a/ui/src/app/connect/components/configuration-group/configuration-group.component.html
+++ b/ui/src/app/connect/components/configuration-group/configuration-group.component.html
@@ -16,7 +16,7 @@
   ~
   -->
 
-<div class="sp-blue-border padding" style="padding: 15px;">
+<div style="padding: 15px;">
     <form [formGroup]="configurationGroup" fxFlex="100">
         <div fxFlex="100" >
             <app-static-property *ngFor="let config of configuration"
diff --git a/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.html b/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.html
index 29c2b08..52aa74a 100644
--- a/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.html
+++ b/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.html
@@ -19,13 +19,23 @@
 <div [className]="className" fxFlex="100"
      fxLayout="column">
     <div fxLayout="column">
-        <div class="type" fxLayout="column" fxLayoutAlign="start start">
-            <div class="type-data" fxLayout="row" fxLayoutAlign="start start">
+        <div class="type" fxLayout="row" fxLayoutAlign="start start" fxFlex="100">
+            <div class="type-data" fxLayout="row" fxLayoutAlign="start center" fxFlex>
                 <mat-icon *ngIf="isDataSetDescription" class="historic">lens</mat-icon>
                 <mat-icon *ngIf="isDataStreamDescription" class="real-time">lens</mat-icon>
                 <p *ngIf="isDataSetDescription">Data Set</p>
                 <p *ngIf="isDataStreamDescription">Data Stream</p>
             </div>
+            <div fxLayout="row" fxLayoutAlign="end end" style="margin-left:5px;">
+                <button class="small-button-add mat-basic no-min-width" (click)="$event.stopPropagation();"
+                        mat-raised-button mat-button [matMenuTriggerFor]="menu"><span style="font-size:12px;">...</span></button>
+                <mat-menu #menu="matMenu">
+                    <button mat-menu-item (click)="removeAdapter()">
+                        <mat-icon>delete</mat-icon>
+                        <span>&nbsp;Remove adapter</span>
+                    </button>
+                </mat-menu>
+            </div>
         </div>
         <div fxLayoutAlign="start center" fxLayout="column" class="icon">
             <img *ngIf="getIconUrl() && !adapter.icon" [src]="getIconUrl()" class="iconImg"/>
diff --git a/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.ts b/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.ts
index 5551963..c65fa3b 100644
--- a/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.ts
+++ b/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.ts
@@ -18,11 +18,11 @@
 
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { ConnectService } from '../../../services/connect.service';
-import { DataMarketplaceService } from '../../../services/data-marketplace.service';
 import { AdapterExportDialog } from '../../../dialog/adapter-export/adapter-export-dialog.component';
 import { MatDialog } from '@angular/material/dialog';
-import { AdapterDescription } from '@streampipes/platform-services';
+import { AdapterDescription, AdapterService } from '@streampipes/platform-services';
 import { DialogService, PanelType } from '@streampipes/shared-ui';
+import { MatSnackBar } from '@angular/material/snack-bar';
 
 @Component({
   selector: 'sp-adapter-description',
@@ -49,9 +49,10 @@
   adapterLabel: string;
 
   constructor(private connectService: ConnectService,
-              private dataMarketplaceService: DataMarketplaceService,
+              private dataMarketplaceService: AdapterService,
               private dialogService: DialogService,
-              public dialog: MatDialog) {
+              public dialog: MatDialog,
+              private _snackBar: MatSnackBar) {
   }
 
   ngOnInit() {
@@ -112,4 +113,12 @@
       return `assets/img/connect/${this.adapter.iconUrl}`;
     }
   }
+
+  removeAdapter(): void {
+    this.dataMarketplaceService.deleteAdapterDescription(this.adapter.elementId).subscribe(res => {
+      this.updateAdapterEmitter.emit();
+    }, error => {
+      this._snackBar.open('Cannot delete an adapter which has an active instance running.');
+    });
+  }
 }
diff --git a/ui/src/app/connect/components/data-marketplace/data-marketplace.component.html b/ui/src/app/connect/components/data-marketplace/data-marketplace.component.html
index 07e0171..61d9949 100644
--- a/ui/src/app/connect/components/data-marketplace/data-marketplace.component.html
+++ b/ui/src/app/connect/components/data-marketplace/data-marketplace.component.html
@@ -16,98 +16,46 @@
   ~
   -->
 
-<div fxLayout="column" fxFlex="100" class="page-container page-container-padding page-container-connect">
-    <div fxLayout="row" style="padding:0px;" class="sp-tab-bg">
-        <div fxLayout="fill" class="page-container-nav">
-            <mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="selectedIndexChange($event)"
-                           color="accent">
-                <mat-tab label="Data Marketplace">
-                </mat-tab>
-                <mat-tab id="all-adapters" label="My Adapters">
-                </mat-tab>
-            </mat-tab-group>
-        </div>
+<sp-basic-view showBackLink="true" [backLinkTarget]="['connect']" [padding]="true">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row">
+        <sp-connect-filter-toolbar
+                class="filter-bar-margin"
+                (filterChangedEmitter)="applyFilter($event)">
+        </sp-connect-filter-toolbar>
         <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center"
-             style="padding-left:10px;padding-right:10px;font-size:14px;" class="page-container-nav"
-             *ngIf="selectedIndex === 0 && newAdapterFromDescription === undefined">
+             style="padding-left:10px;padding-right:10px;font-size:14px;" class="page-container-nav">
             <button mat-icon-button id="startAdapterTutorial3" (click)="startAdapterTutorial3()"
                     matTooltip="Tutorial: Generic Adapter">
                 <mat-icon color="accent">school</mat-icon>
             </button>
         </div>
     </div>
-
-    <div fxLayout="row" class="fixed-height data-marketplace-options">
-
-        <div class="data-marketplace-options-item pl-5" style="margin-top:8px;" fxLayoutAlign="start center"
-             fxLayout="row">
-            <mat-icon color="accent">search</mat-icon>
-            <mat-form-field class="form-style">
-                <input matInput placeholder="Find Element" value="" (input)="updateFilterTerm($event.target.value)"
-                       name="something">
-            </mat-form-field>
-        </div>
-        <div class="data-marketplace-options-item">
-            <mat-form-field color="accent">
-                <mat-select [(value)]="selectedType" (selectionChange)="filterAdapter($event)">
-                    <mat-option *ngFor="let type of adapterTypes" [value]="type">
-                        {{type}}
-                    </mat-option>
-                </mat-select>
-            </mat-form-field>
-        </div>
-        <div class="data-marketplace-options-item">
-            <mat-form-field color="accent">
-                <mat-select [(value)]="selectedCategory" (selectionChange)="filterAdapter($event)">
-                    <mat-option *ngFor="let category of adapterCategories" [value]="category.code">
-                        {{category.label}}
-                    </mat-option>
-                </mat-select>
-            </mat-form-field>
-        </div>
-        <span fxFlex></span>
-
-    </div>
-    <div class="container-fluid marketplace-container" *ngIf="adapterLoadingError" fxFlex="100"
-         fxLayoutAlign="center center" fxLayout="row">
-        <h4>Available adapters could not be loaded. Did you start a Connect worker node?</h4>
-    </div>
-    <div class="container-fluid marketplace-container" *ngIf="adaptersLoading" fxFlex="100"
-         fxLayoutAlign="center center" fxLayout="row">
-        <mat-spinner [mode]="'indeterminate'" [diameter]="20" color="accent"></mat-spinner>
-        <h4>&nbsp;&nbsp;Searching for available adapters, please wait...</h4>
-    </div>
-    <div class="container-fluid marketplace-container" *ngIf="!adaptersLoading && !adapterLoadingError">
-        <div *ngIf="selectedIndex === 0">
-
-            <div *ngIf="newAdapterFromDescription===undefined" fxLayout="row wrap" fxLayoutAlign="start stretch"
-                 class="adapter-description-container">
-                <sp-adapter-description attr.id="{{adapterDescription.name.replaceAll(' ', '_')}}"
-                                        class="adapter-description"
-                                        fxFlex="33" (click)="selectAdapter(adapterDescription)"
-                                        *ngFor="let adapterDescription of filteredAdapterDescriptions | filter:filterTerm"
-                                        [adapter]="adapterDescription"
-                                        (updateAdapterEmitter)="updateDescriptionsAndRunningAdatpers()"></sp-adapter-description>
+    <div fxLayout="column" fxFlex="100">
+        <sp-basic-header-title-component title="Select Adapter"></sp-basic-header-title-component>
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
+            <div class="container-fluid marketplace-container" *ngIf="adapterLoadingError" fxFlex="100"
+                 fxLayoutAlign="center center" fxLayout="row">
+                <h4>Available adapters could not be loaded. Did you start a Connect worker node?</h4>
             </div>
-
-
-            <div class="new-adapter-container" fxFlex="100" fxLayout="row" fxLayoutAlign="start start"
-                 *ngIf="newAdapterFromDescription!==undefined">
-                <sp-new-adapter fxFlex="100" (removeSelectionEmitter)="removeSelection($event)"
-                                [adapter]="newAdapterFromDescription"
-                                (updateAdapterEmitter)="updateDescriptionsAndRunningAdatpers()"></sp-new-adapter>
+            <div class="container-fluid marketplace-container" *ngIf="adaptersLoading" fxFlex="100"
+                 fxLayoutAlign="center center" fxLayout="row">
+                <mat-spinner [mode]="'indeterminate'" [diameter]="20" color="accent"></mat-spinner>
+                <h4>&nbsp;&nbsp;Searching for available adapters, please wait...</h4>
             </div>
-
-        </div>
-        <div *ngIf="selectedIndex === 1">
-            <div fxFlex="100" class="adapter-container">
-                <sp-existing-adapters [existingAdapters]="filteredAdapters"
-                                      [filterTerm]="filterTerm"
-                                      (updateAdapterEmitter)="updateDescriptionsAndRunningAdatpers()"
-                                      (createTemplateEmitter)="templateFromRunningAdapter($event)">
-
-                </sp-existing-adapters>
+            <div class="container-fluid marketplace-container"
+                 *ngIf="!adaptersLoading && !adapterLoadingError && currentFilter">
+                <div fxLayout="row wrap" fxLayoutAlign="start stretch"
+                     class="adapter-description-container">
+                    <sp-adapter-description attr.id="{{adapterDescription.name.replaceAll(' ', '_')}}"
+                                            class="adapter-description"
+                                            fxFlex="33"
+                                            (updateAdapterEmitter)="getAdapterDescriptions()"
+                                            (click)="selectAdapter(adapterDescription.appId)"
+                                            *ngFor="let adapterDescription of adapterDescriptions | adapterFilter:currentFilter"
+                                            [adapter]="adapterDescription"></sp-adapter-description>
+                </div>
             </div>
         </div>
     </div>
-</div>
+</sp-basic-view>
diff --git a/ui/src/app/connect/components/data-marketplace/data-marketplace.component.scss b/ui/src/app/connect/components/data-marketplace/data-marketplace.component.scss
index 9034535..6f91e02 100644
--- a/ui/src/app/connect/components/data-marketplace/data-marketplace.component.scss
+++ b/ui/src/app/connect/components/data-marketplace/data-marketplace.component.scss
@@ -46,38 +46,15 @@
   background: #EEE;
 }
 
-#categoryFilter {
-  margin-top: 20px;
-}
-
-.fixed-height {
-  height: 50px;
-}
-
-.form-style {
-  margin: 0px 5px 0px 0px;
-}
-
 .icon-style {
   margin: 15px 4px 0px 0px;
   color: var(--color-accent);
 }
 
-.data-marketplace-options {
-  padding:0px;
-  background-color: var(--color-bg-1);
-  border-bottom: 1px solid var(--color-bg-3);
+.filter-bar-margin {
+  margin-left: 10px;
+  padding-left: 10px;
 }
 
-.data-marketplace-options-item {
-  display: inline;
-  margin-right: 10px;
-}
 
-::ng-deep .mat-select-panel {
-  background: #fff;
-}
 
-::ng-deep .mat-select-panel:not([class*=mat-elevation-z]) {
-  box-shadow: 0 2px 4px -1px rgba(0,0,0,.2), 0 4px 5px 0 rgba(0,0,0,.14), 0 1px 10px 0 rgba(0,0,0,.12);
-}
diff --git a/ui/src/app/connect/components/data-marketplace/data-marketplace.component.ts b/ui/src/app/connect/components/data-marketplace/data-marketplace.component.ts
index a49adcd..6cf253d 100644
--- a/ui/src/app/connect/components/data-marketplace/data-marketplace.component.ts
+++ b/ui/src/app/connect/components/data-marketplace/data-marketplace.component.ts
@@ -16,13 +16,14 @@
  *
  */
 
-import { Component, EventEmitter, OnInit, Output } from '@angular/core';
-import { DataMarketplaceService } from '../../services/data-marketplace.service';
+import { Component, OnInit } from '@angular/core';
 import { ShepherdService } from '../../../services/tour/shepherd.service';
 import { ConnectService } from '../../services/connect.service';
-import { FilterPipe } from '../../filter/filter.pipe';
-import { AdapterDescriptionUnion } from '@streampipes/platform-services';
-import { DialogService } from '@streampipes/shared-ui';
+import { AdapterDescriptionUnion, AdapterService } from '@streampipes/platform-services';
+import { DialogService, SpBreadcrumbService } from '@streampipes/shared-ui';
+import { Router } from '@angular/router';
+import { AdapterFilterSettingsModel } from '../../model/adapter-filter-settings.model';
+import { SpConnectRoutes } from '../../connect.routes';
 
 @Component({
   selector: 'sp-data-marketplace',
@@ -30,50 +31,25 @@
   styleUrls: ['./data-marketplace.component.scss']
 })
 export class DataMarketplaceComponent implements OnInit {
+
   adapterDescriptions: AdapterDescriptionUnion[];
-  newAdapterFromDescription: AdapterDescriptionUnion;
-  filteredAdapterDescriptions: AdapterDescriptionUnion[];
-  adapters: AdapterDescriptionUnion[];
-  filteredAdapters: AdapterDescriptionUnion[];
-  visibleAdapters: AdapterDescriptionUnion[];
-
-  @Output()
-  selectAdapterEmitter: EventEmitter<AdapterDescriptionUnion> = new EventEmitter<AdapterDescriptionUnion>();
-
-  selectedIndex = 0;
-  filterTerm = '';
-  pipe: FilterPipe = new FilterPipe();
-  adapterTypes: string[] = ['All types', 'Data Set', 'Data Stream'];
-  selectedType = 'All types';
-
-  adapterCategories: any;
-  selectedCategory: any = 'All';
 
   adaptersLoading = true;
   adapterLoadingError = false;
 
-  constructor(private dataMarketplaceService: DataMarketplaceService,
+  currentFilter: AdapterFilterSettingsModel;
+
+  constructor(private dataMarketplaceService: AdapterService,
               private shepherdService: ShepherdService,
               private connectService: ConnectService,
-              private dialogService: DialogService) {
+              private dialogService: DialogService,
+              private router: Router,
+              private breadcrumbService: SpBreadcrumbService) {
   }
 
   ngOnInit() {
-    this.updateDescriptionsAndRunningAdatpers();
-    this.loadAvailableTypeCategories();
-    this.visibleAdapters = this.adapters;
-  }
-
-  loadAvailableTypeCategories() {
-    this.dataMarketplaceService.getAdapterCategories().subscribe(res => {
-      this.adapterCategories = res;
-      this.adapterCategories.unshift({ label: 'All categories', description: '', code: 'All' });
-    });
-  }
-
-  updateDescriptionsAndRunningAdatpers() {
+    this.breadcrumbService.updateBreadcrumb([SpConnectRoutes.BASE, this.breadcrumbService.removeLink(SpConnectRoutes.CREATE)]);
     this.getAdapterDescriptions();
-    this.getAdaptersRunning();
   }
 
   getAdapterDescriptions(): void {
@@ -84,10 +60,8 @@
       .getAdapterDescriptions()
       .subscribe((allAdapters) => {
         this.adapterDescriptions = allAdapters;
-        // this.adapterDescriptions = this.adapterDescriptions.concat(allAdapters[1]);
         this.adapterDescriptions
           .sort((a, b) => a.name.localeCompare(b.name));
-        this.filteredAdapterDescriptions = this.adapterDescriptions;
         this.adaptersLoading = false;
       }, error => {
         console.log(error);
@@ -96,17 +70,6 @@
       });
   }
 
-  getAdaptersRunning(): void {
-    this.dataMarketplaceService.getAdapters().subscribe(adapters => {
-      this.adapters = adapters;
-      this.filteredAdapters = this.adapters;
-    });
-  }
-
-  selectedIndexChange(index: number) {
-    this.selectedIndex = index;
-  }
-
   startAdapterTutorial() {
     this.shepherdService.startAdapterTour();
   }
@@ -119,58 +82,12 @@
     this.shepherdService.startAdapterTour3();
   }
 
-  selectAdapter(adapterDescription: AdapterDescriptionUnion) {
-    this.newAdapterFromDescription = this.dataMarketplaceService.cloneAdapterDescription(adapterDescription);
-    (this.newAdapterFromDescription as any).templateTitle = this.newAdapterFromDescription.name;
-    this.newAdapterFromDescription.name = '';
-    this.newAdapterFromDescription.description = '';
-
-    this.shepherdService.trigger('select-adapter');
+  selectAdapter(appId: string) {
+    this.router.navigate(['connect', 'create', appId]);
+    // this.shepherdService.trigger('select-adapter');
   }
 
-  templateFromRunningAdapter(adapter: AdapterDescriptionUnion) {
-    adapter.elementId = undefined;
-    adapter._rev = undefined;
-    this.selectedIndexChange(0);
-    this.selectAdapter(adapter);
-
+  applyFilter(filter: AdapterFilterSettingsModel) {
+    this.currentFilter = { ...filter };
   }
-
-  removeSelection() {
-    this.newAdapterFromDescription = undefined;
-  }
-
-  updateFilterTerm(inputValue) {
-    this.filterTerm = inputValue;
-  }
-
-  filterAdapter(event) {
-    const filteredAdapterTypes = this.filterAdapterType(this.adapterDescriptions);
-    const filteredAdapterTemplateTypes = this.filterAdapterType(this.adapters);
-
-    const filteredAdapterCategories = this.filterAdapterCategory(filteredAdapterTypes);
-    const filteredAdapterTemplateCategories = this.filterAdapterCategory(filteredAdapterTemplateTypes);
-
-    this.filteredAdapterDescriptions = filteredAdapterCategories;
-    this.filteredAdapters = filteredAdapterTemplateCategories;
-  }
-
-  filterAdapterCategory(currentElements: AdapterDescriptionUnion[]): AdapterDescriptionUnion[] {
-    if (this.selectedCategory === this.adapterCategories[0].code) {
-      return currentElements;
-    } else {
-      return currentElements.filter(adapterDescription => adapterDescription.category.indexOf(this.selectedCategory) !== -1);
-    }
-  }
-
-  filterAdapterType(currentElements: AdapterDescriptionUnion[]): AdapterDescriptionUnion[] {
-    if (this.selectedType === this.adapterTypes[0]) {
-      return currentElements;
-    } else if (this.selectedType === this.adapterTypes[1]) {
-      return currentElements.filter(adapterDescription => this.connectService.isDataSetDescription(adapterDescription));
-    } else if (this.selectedType === this.adapterTypes[2]) {
-      return currentElements.filter(adapterDescription => !this.connectService.isDataSetDescription(adapterDescription));
-    }
-  }
-
 }
diff --git a/ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.html b/ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.html
deleted file mode 100644
index d1ee145..0000000
--- a/ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.html
+++ /dev/null
@@ -1,146 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div fxFlex="100" fxLayout="column">
-    <div class="assemblyOptions sp-blue-bg mt-20" style="padding:5px;">
-        <div fxLayout="row" fxLayoutAlign="start center">
-            <h4>My adapters</h4>
-            <span fxFlex></span>
-            <button mat-button mat-icon-button matTooltip="Refresh adapters" matTooltipPosition="above"
-                    (click)="updateAdapterEmitter.emit()">
-                <i class="material-icons">
-                    refresh
-                </i>
-            </button>
-        </div>
-    </div>
-    <div class="sp-blue-border">
-        <table fxFlex="100" mat-table [dataSource]="dataSource" style="width: 100%;" matSort>
-            <ng-container matColumnDef="start">
-                <th mat-header-cell *matHeaderCellDef> Start</th>
-                <td mat-cell *matCellDef="let adapter">
-                    <button color="accent" mat-button mat-icon-button matTooltip="Start adapter"
-                            matTooltipPosition="above"
-                            (click)="startAdapter(adapter)"
-                            *ngIf="(connectService.isDataStreamDescription(adapter)) && !adapter.running">
-                        <i class="material-icons">play_arrow</i>
-                    </button>
-                    <button color="accent" mat-button mat-icon-button matTooltip="Stop adapter"
-                            matTooltipPosition="above"
-                            (click)="stopAdapter(adapter)"
-                            *ngIf="(connectService.isDataStreamDescription(adapter)) && adapter.running">
-                        <i class="material-icons">stop</i>
-                    </button>
-                </td>
-            </ng-container>
-
-            <ng-container matColumnDef="name">
-                <th mat-header-cell mat-sort-header *matHeaderCellDef> Name</th>
-                <td mat-cell *matCellDef="let adapter">
-                    <h4 style="margin-bottom:0px;">{{adapter.name}}</h4>
-                    <h5>{{adapter.description != '' ? adapter.description : '-'}}</h5>
-                </td>
-            </ng-container>
-            <ng-container matColumnDef="adapterBase">
-                <th mat-header-cell *matHeaderCellDef> Adapter</th>
-                <td mat-cell *matCellDef="let adapter">
-                    <img *ngIf="getIconUrl(adapter) && !adapter.icon" [src]="getIconUrl(adapter)" class="adapter-icon"/>
-                    <img *ngIf="adapter.icon" [src]="adapter.icon" class="adapter-icon"/>
-                </td>
-            </ng-container>
-            <ng-container matColumnDef="adapterType">
-                <th mat-header-cell *matHeaderCellDef> Type</th>
-                <td mat-cell *matCellDef="let adapter">
-                    <div class="type-data" fxLayout="row" fxLayoutAlign="start start">
-                        <div fxLayout="row" fxLayoutAlign="center center">
-                            <mat-icon *ngIf="connectService.isDataSetDescription(adapter)" class="historic">lens
-                            </mat-icon>
-                            <mat-icon *ngIf="connectService.isDataStreamDescription(adapter)" class="real-time">lens
-                            </mat-icon>
-                            <div fxFlex="100" fxLayoutAlign="center center">
-                                <span *ngIf="connectService.isDataSetDescription(adapter)">&nbsp;Data Set</span>
-                                <span *ngIf="connectService.isDataStreamDescription(adapter)">&nbsp;Data Stream</span>
-                            </div>
-                        </div>
-                    </div>
-                </td>
-            </ng-container>
-            <ng-container matColumnDef="lastModified">
-                <th mat-header-cell *matHeaderCellDef> Created</th>
-                <td mat-cell *matCellDef="let adapter">
-                    <h5>{{adapter.createdAt | date:'dd.MM.yyyy HH:mm'}}</h5>
-                </td>
-            </ng-container>
-
-            <ng-container matColumnDef="action">
-                <th mat-header-cell *matHeaderCellDef> Action</th>
-                <td mat-cell *matCellDef="let adapter">
-                    <div fxLayout="row">
-                        <!--                <span fxFlex fxFlexOrder="1" fxLayout="row" fxLayoutAlign="center center">-->
-                        <!--                    <button color="primary" mat-button mat-icon-button matTooltip="Show adapter"-->
-                        <!--                            matTooltipPosition="above"><i-->
-                        <!--                            class="material-icons">search</i>-->
-                        <!--                    </button>-->
-                        <!--                </span>-->
-                        <!--                        <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center">-->
-                        <!--                    <button color="primary" mat-button mat-icon-button matTooltip="Modify adapter"-->
-                        <!--                            matTooltipPosition="above"-->
-                        <!--                            [disabled]="adapter.running">-->
-                        <!--                        <i class="material-icons">mode_edit</i>-->
-                        <!--                    </button>-->
-                        <!--                </span>-->
-                <span fxFlex fxFlexOrder="1" fxLayout="row" fxLayoutAlign="center center">
-                    <button color="accent" mat-button mat-icon-button matTooltip="Show info"
-                            matTooltipPosition="above" (click)="openHelpDialog(adapter)"><i
-                            class="material-icons">help_outline</i>
-                    </button>
-                </span>
-                <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center">
-                    <button color="accent" mat-button mat-icon-button matTooltip="Create adapter template"
-                            matTooltipPosition="above" (click)="createTemplate(adapter)"><i
-                            class="material-icons">content_copy</i>
-                    </button>
-                </span>
-                        <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center" *ngIf="isAdmin">
-                    <button color="accent" mat-button mat-icon-button matTooltip="Manage permissions"
-                            matTooltipPosition="above" (click)="showPermissionsDialog(adapter)"><i
-                            class="material-icons">share</i>
-                    </button>
-                </span>
-                        <span fxFlex fxFlexOrder="4" fxLayout="row" fxLayoutAlign="center center">
-                    <button color="accent" mat-button mat-icon-button matTooltip="Delete adapter"
-                            data-cy="delete" matTooltipPosition="above" (click)="deleteAdapter(adapter)">
-                        <i class="material-icons">delete</i>
-                    </button>
-                </span>
-                    </div>
-                </td>
-            </ng-container>
-
-            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
-            <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
-
-        </table>
-    </div>
-    <div fxFlex="100" fxLayoutAlign="end end">
-        <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]="20"></mat-paginator>
-    </div>
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="center center" *ngIf="existingAdapters.length == 0">
-        <h5>(no adapters available)</h5>
-    </div>
-</div>
diff --git a/ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.ts b/ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.ts
deleted file mode 100644
index 6b3f42e..0000000
--- a/ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.ts
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
-import { AdapterDescriptionUnion, PipelineElementService } from '@streampipes/platform-services';
-import { MatTableDataSource } from '@angular/material/table';
-import { ConnectService } from '../../../services/connect.service';
-import { DataMarketplaceService } from '../../../services/data-marketplace.service';
-import { DialogRef, PanelType, DialogService } from '@streampipes/shared-ui';
-import { DeleteAdapterDialogComponent } from '../../../dialog/delete-adapter-dialog/delete-adapter-dialog.component';
-import { MatPaginator } from '@angular/material/paginator';
-import { MatSort } from '@angular/material/sort';
-import { ObjectPermissionDialogComponent } from '../../../../core-ui/object-permission-dialog/object-permission-dialog.component';
-import { UserRole } from '../../../../_enums/user-role.enum';
-import { AuthService } from '../../../../services/auth.service';
-import { HelpComponent } from '../../../../editor/dialog/help/help.component';
-
-@Component({
-  selector: 'sp-existing-adapters',
-  templateUrl: './existing-adapters.component.html',
-  styleUrls: ['./existing-adapters.component.scss']
-})
-export class ExistingAdaptersComponent implements OnInit {
-
-  _existingAdapters: AdapterDescriptionUnion[];
-
-  @Input()
-  filterTerm: string;
-
-  @Output()
-  updateAdapterEmitter: EventEmitter<void> = new EventEmitter<void>();
-
-  @Output()
-  createTemplateEmitter: EventEmitter<AdapterDescriptionUnion> = new EventEmitter<AdapterDescriptionUnion>();
-
-  @ViewChild(MatPaginator) paginator: MatPaginator;
-  pageSize = 1;
-  @ViewChild(MatSort) sort: MatSort;
-
-  displayedColumns: string[] = ['start', 'name', 'adapterBase', 'adapterType', 'lastModified', 'action'];
-
-  dataSource: MatTableDataSource<AdapterDescriptionUnion>;
-  isAdmin = false;
-
-  constructor(public connectService: ConnectService,
-              private dataMarketplaceService: DataMarketplaceService,
-              private dialogService: DialogService,
-              private authService: AuthService,
-              private pipelineElementService: PipelineElementService) {
-
-  }
-
-  ngOnInit(): void {
-    this.authService.user$.subscribe(user => {
-      this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
-    });
-    this.dataSource = new MatTableDataSource(this.existingAdapters);
-    setTimeout(() => {
-      this.dataSource.paginator = this.paginator;
-      this.dataSource.sort = this.sort;
-    });
-  }
-
-  startAdapter(adapter: AdapterDescriptionUnion) {
-    this.dataMarketplaceService.startAdapter(adapter).subscribe(response => {
-      this.updateAdapterEmitter.emit();
-    });
-  }
-
-  stopAdapter(adapter: AdapterDescriptionUnion) {
-    this.dataMarketplaceService.stopAdapter(adapter).subscribe(response => {
-      this.updateAdapterEmitter.emit();
-    });
-  }
-
-  getIconUrl(adapter: AdapterDescriptionUnion) {
-    if (adapter.includedAssets.length > 0) {
-      return this.dataMarketplaceService.getAssetUrl(adapter.appId) + '/icon';
-    } else {
-      return 'assets/img/connect/' + adapter.iconUrl;
-    }
-  }
-
-  showPermissionsDialog(adapter: AdapterDescriptionUnion) {
-
-    const dialogRef = this.dialogService.open(ObjectPermissionDialogComponent, {
-      panelType: PanelType.SLIDE_IN_PANEL,
-      title: 'Manage permissions',
-      width: '50vw',
-      data: {
-        'objectInstanceId': adapter.correspondingDataStreamElementId,
-        'headerTitle': 'Manage permissions for adapter ' + adapter.name
-      }
-    });
-
-    dialogRef.afterClosed().subscribe(refresh => {
-      if (refresh) {
-        this.updateAdapterEmitter.emit();
-      }
-    });
-  }
-
-  deleteAdapter(adapter: AdapterDescriptionUnion): void {
-    const dialogRef: DialogRef<DeleteAdapterDialogComponent> = this.dialogService.open(DeleteAdapterDialogComponent, {
-      panelType: PanelType.STANDARD_PANEL,
-      title: 'Delete Adapter',
-      width: '70vw',
-      data: {
-        'adapter': adapter
-      }
-    });
-
-    dialogRef.afterClosed().subscribe(data => {
-      if (data) {
-        this.updateAdapterEmitter.emit();
-      }
-    });
-  }
-
-  openHelpDialog(adapter: AdapterDescriptionUnion) {
-    const streamId = adapter.correspondingDataStreamElementId;
-
-    this.pipelineElementService.getDataStreamByElementId(streamId).subscribe(stream => {
-      if (stream) {
-        this.dialogService.open(HelpComponent, {
-          panelType: PanelType.STANDARD_PANEL,
-          title: stream.name,
-          width: '70vw',
-          data: {
-            'pipelineElement': stream
-          }
-        });
-      }
-    });
-  }
-
-
-  createTemplate(adapter: AdapterDescriptionUnion): void {
-    this.createTemplateEmitter.emit(adapter);
-  }
-
-  @Input()
-  set existingAdapters(adapters: AdapterDescriptionUnion[]) {
-    this._existingAdapters = adapters;
-    this.dataSource = new MatTableDataSource(adapters);
-  }
-
-  get existingAdapters(): AdapterDescriptionUnion[] {
-    return this._existingAdapters;
-  }
-
-}
diff --git a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
new file mode 100644
index 0000000..102666f
--- /dev/null
+++ b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
@@ -0,0 +1,157 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<sp-basic-view [showBackLink]="false" [padding]="true">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                data-cy="connect-create-new-adapter-button"
+                (click)="createNewAdapter()">
+            <i class="material-icons">add</i>&nbsp;New adapter
+        </button>
+        <sp-connect-filter-toolbar
+                class="filter-bar-margin"
+                (filterChangedEmitter)="applyFilter($event)">
+        </sp-connect-filter-toolbar>
+        <div fxFlex fxLayout="row" fxLayoutAlign="end center">
+            <button mat-button mat-icon-button matTooltip="Refresh adapters" matTooltipPosition="below" color="accent"
+                    (click)="getAdaptersRunning()">
+                <i class="material-icons">
+                    refresh
+                </i>
+            </button>
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="column">
+        <sp-basic-header-title-component title="My adapters"></sp-basic-header-title-component>
+        <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+            <sp-basic-inner-panel [showTitle]="false" innerPadding="0" outerMargin="0" fxFlex="90" [hideToolbar]="true">
+                <div fxFlex="100" fxLayout="column" *ngIf="filteredAdapters.length > 0">
+                    <div fxFlex="100" fxLayout="column">
+                        <table fxFlex="100" mat-table [dataSource]="dataSource" style="width: 100%;" matSort>
+                            <ng-container matColumnDef="start">
+                                <th mat-header-cell *matHeaderCellDef> Start</th>
+                                <td mat-cell *matCellDef="let adapter">
+                                    <button color="accent" mat-button mat-icon-button matTooltip="Start adapter"
+                                            matTooltipPosition="above"
+                                            (click)="startAdapter(adapter)"
+                                            *ngIf="(connectService.isDataStreamDescription(adapter)) && !adapter.running">
+                                        <i class="material-icons">play_arrow</i>
+                                    </button>
+                                    <button color="accent" mat-button mat-icon-button matTooltip="Stop adapter"
+                                            matTooltipPosition="above"
+                                            (click)="stopAdapter(adapter)"
+                                            *ngIf="(connectService.isDataStreamDescription(adapter)) && adapter.running">
+                                        <i class="material-icons">stop</i>
+                                    </button>
+                                </td>
+                            </ng-container>
+
+                            <ng-container matColumnDef="name">
+                                <th mat-header-cell mat-sort-header *matHeaderCellDef> Name</th>
+                                <td mat-cell *matCellDef="let adapter">
+                                    <h4 style="margin-bottom:0px;">{{adapter.name}}</h4>
+                                    <h5>{{adapter.description != '' ? adapter.description : '-'}}</h5>
+                                </td>
+                            </ng-container>
+                            <ng-container matColumnDef="adapterBase">
+                                <th mat-header-cell *matHeaderCellDef> Adapter</th>
+                                <td mat-cell *matCellDef="let adapter">
+                                    <img *ngIf="getIconUrl(adapter) && !adapter.icon" [src]="getIconUrl(adapter)"
+                                         class="adapter-icon"/>
+                                    <img *ngIf="adapter.icon" [src]="adapter.icon" class="adapter-icon"/>
+                                </td>
+                            </ng-container>
+                            <ng-container matColumnDef="adapterType">
+                                <th mat-header-cell *matHeaderCellDef> Type</th>
+                                <td mat-cell *matCellDef="let adapter">
+                                    <div class="type-data" fxLayout="row" fxLayoutAlign="start start">
+                                        <div fxLayout="row" fxLayoutAlign="center center">
+                                            <mat-icon *ngIf="connectService.isDataSetDescription(adapter)"
+                                                      class="historic">
+                                                lens
+                                            </mat-icon>
+                                            <mat-icon *ngIf="connectService.isDataStreamDescription(adapter)"
+                                                      class="real-time">
+                                                lens
+                                            </mat-icon>
+                                            <div fxFlex="100" fxLayoutAlign="center center">
+                                                <span *ngIf="connectService.isDataSetDescription(adapter)">&nbsp;Data Set</span>
+                                                <span *ngIf="connectService.isDataStreamDescription(adapter)">&nbsp;Data Stream</span>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </td>
+                            </ng-container>
+                            <ng-container matColumnDef="lastModified">
+                                <th mat-header-cell *matHeaderCellDef> Created</th>
+                                <td mat-cell *matCellDef="let adapter">
+                                    <h5>{{adapter.createdAt | date:'dd.MM.yyyy HH:mm'}}</h5>
+                                </td>
+                            </ng-container>
+
+                            <ng-container matColumnDef="action">
+                                <th mat-header-cell *matHeaderCellDef> Action</th>
+                                <td mat-cell *matCellDef="let adapter">
+                                    <div fxLayout="row">
+                            <span fxFlex fxFlexOrder="1" fxLayout="row" fxLayoutAlign="center center">
+                    <button color="accent" mat-button mat-icon-button matTooltip="Show info"
+                            matTooltipPosition="above" (click)="openHelpDialog(adapter)"><i
+                            class="material-icons">help_outline</i>
+                    </button>
+                        </span>
+                                        <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center"
+                                              *ngIf="isAdmin">
+                    <button color="accent" mat-button mat-icon-button matTooltip="Manage permissions"
+                            matTooltipPosition="above" (click)="showPermissionsDialog(adapter)"><i
+                            class="material-icons">share</i>
+                    </button>
+                </span>
+                                        <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center">
+                    <button color="accent" mat-button mat-icon-button matTooltip="Delete adapter"
+                            data-cy="delete-adapter" matTooltipPosition="above" (click)="deleteAdapter(adapter)">
+                        <i class="material-icons">delete</i>
+                    </button>
+                </span>
+                                    </div>
+                                </td>
+                            </ng-container>
+
+                            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                            <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+
+                        </table>
+                    </div>
+                    <div fxFlex="100" fxLayoutAlign="end end">
+                        <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"
+                                       [pageSize]="20"
+                                       color="accent">
+                        </mat-paginator>
+                    </div>
+                </div>
+                <div fxFlex="100"
+                     fxLayout="column"
+                     fxLayoutAlign="center center"
+                     *ngIf="existingAdapters.length == 0">
+                    <h5>(no adapters available)</h5>
+                </div>
+            </sp-basic-inner-panel>
+        </div>
+    </div>
+</sp-basic-view>
diff --git a/ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.scss b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.scss
similarity index 91%
rename from ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.scss
rename to ui/src/app/connect/components/existing-adapters/existing-adapters.component.scss
index b69117a..f38f54d 100644
--- a/ui/src/app/connect/components/data-marketplace/existing-adapters/existing-adapters.component.scss
+++ b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.scss
@@ -26,10 +26,10 @@
 }
 
 .mat-row:nth-child(even) {
-  background-color: var(--color-bg-2);
+  background-color: var(--color-bg-1);
 }
 .mat-row:nth-child(odd) {
-  background-color: var(--color-bg-3);
+  background-color: var(--color-bg-2);
 }
 
 .adapter-icon {
@@ -44,3 +44,9 @@
   cursor: pointer;
   color: #FFEB3B;
 }
+
+.filter-bar-margin {
+  margin-left: 10px;
+  padding-left: 10px;
+}
+
diff --git a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
new file mode 100644
index 0000000..ecee3df
--- /dev/null
+++ b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit, ViewChild } from '@angular/core';
+import {
+  AdapterDescriptionUnion,
+  AdapterService,
+  PipelineElementService,
+  StreamPipesErrorMessage
+} from '@streampipes/platform-services';
+import { MatTableDataSource } from '@angular/material/table';
+import { ConnectService } from '../../services/connect.service';
+import {
+  DialogRef,
+  DialogService,
+  PanelType,
+  SpBreadcrumbService,
+  SpExceptionDetailsDialogComponent
+} from '@streampipes/shared-ui';
+import { DeleteAdapterDialogComponent } from '../../dialog/delete-adapter-dialog/delete-adapter-dialog.component';
+import { MatPaginator } from '@angular/material/paginator';
+import { MatSort } from '@angular/material/sort';
+import { ObjectPermissionDialogComponent } from '../../../core-ui/object-permission-dialog/object-permission-dialog.component';
+import { UserRole } from '../../../_enums/user-role.enum';
+import { AuthService } from '../../../services/auth.service';
+import { HelpComponent } from '../../../editor/dialog/help/help.component';
+import { Router } from '@angular/router';
+import { AdapterFilterSettingsModel } from '../../model/adapter-filter-settings.model';
+import { AdapterFilterPipe } from '../../filter/adapter-filter.pipe';
+import { SpConnectRoutes } from '../../connect.routes';
+
+@Component({
+  selector: 'sp-existing-adapters',
+  templateUrl: './existing-adapters.component.html',
+  styleUrls: ['./existing-adapters.component.scss']
+})
+export class ExistingAdaptersComponent implements OnInit {
+
+  existingAdapters: AdapterDescriptionUnion[] = [];
+  filteredAdapters: AdapterDescriptionUnion[] = [];
+
+  currentFilter: AdapterFilterSettingsModel;
+
+  @ViewChild(MatPaginator) paginator: MatPaginator;
+  pageSize = 1;
+  @ViewChild(MatSort) sort: MatSort;
+
+  displayedColumns: string[] = ['start', 'name', 'adapterBase', 'adapterType', 'lastModified', 'action'];
+
+  dataSource: MatTableDataSource<AdapterDescriptionUnion>;
+  isAdmin = false;
+
+  constructor(public connectService: ConnectService,
+              private dataMarketplaceService: AdapterService,
+              private dialogService: DialogService,
+              private authService: AuthService,
+              private pipelineElementService: PipelineElementService,
+              private router: Router,
+              private adapterFilter: AdapterFilterPipe,
+              private breadcrumbService: SpBreadcrumbService) {
+
+  }
+
+  ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpConnectRoutes.BASE));
+    this.authService.user$.subscribe(user => {
+      this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
+      this.getAdaptersRunning();
+    });
+  }
+
+  startAdapter(adapter: AdapterDescriptionUnion) {
+    this.dataMarketplaceService.startAdapter(adapter).subscribe(response => {
+      this.getAdaptersRunning();
+    }, error => {
+      this.openAdapterStatusErrorDialog(error.error, 'Could not start adapter');
+    });
+  }
+
+  stopAdapter(adapter: AdapterDescriptionUnion) {
+    this.dataMarketplaceService.stopAdapter(adapter).subscribe(response => {
+      this.getAdaptersRunning();
+    }, error => {
+      this.openAdapterStatusErrorDialog(error.error, 'Could not stop adapter');
+    });
+  }
+
+  openAdapterStatusErrorDialog(message: StreamPipesErrorMessage,
+                               title: string) {
+    this.dialogService.open(SpExceptionDetailsDialogComponent, {
+      panelType: PanelType.STANDARD_PANEL,
+      title: 'Adapter Status',
+      width: '70vw',
+      data: {
+        'message': message,
+        'title': title
+      }
+    });
+  }
+
+  getIconUrl(adapter: AdapterDescriptionUnion) {
+    if (adapter.includedAssets.length > 0) {
+      return this.dataMarketplaceService.getAssetUrl(adapter.appId) + '/icon';
+    } else {
+      return 'assets/img/connect/' + adapter.iconUrl;
+    }
+  }
+
+  showPermissionsDialog(adapter: AdapterDescriptionUnion) {
+
+    const dialogRef = this.dialogService.open(ObjectPermissionDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Manage permissions',
+      width: '50vw',
+      data: {
+        'objectInstanceId': adapter.correspondingDataStreamElementId,
+        'headerTitle': 'Manage permissions for adapter ' + adapter.name
+      }
+    });
+
+    dialogRef.afterClosed().subscribe(refresh => {
+      if (refresh) {
+        this.getAdaptersRunning();
+      }
+    });
+  }
+
+  deleteAdapter(adapter: AdapterDescriptionUnion): void {
+    const dialogRef: DialogRef<DeleteAdapterDialogComponent> = this.dialogService.open(DeleteAdapterDialogComponent, {
+      panelType: PanelType.STANDARD_PANEL,
+      title: 'Delete Adapter',
+      width: '70vw',
+      data: {
+        'adapter': adapter
+      }
+    });
+
+    dialogRef.afterClosed().subscribe(data => {
+      if (data) {
+        this.getAdaptersRunning();
+      }
+    });
+  }
+
+  openHelpDialog(adapter: AdapterDescriptionUnion) {
+    const streamId = adapter.correspondingDataStreamElementId;
+
+    this.pipelineElementService.getDataStreamByElementId(streamId).subscribe(stream => {
+      if (stream) {
+        this.dialogService.open(HelpComponent, {
+          panelType: PanelType.STANDARD_PANEL,
+          title: stream.name,
+          width: '70vw',
+          data: {
+            'pipelineElement': stream
+          }
+        });
+      }
+    });
+  }
+
+  getAdaptersRunning(): void {
+    this.dataMarketplaceService.getAdapters().subscribe(adapters => {
+      this.existingAdapters = adapters;
+      this.existingAdapters.sort((a, b) => a.name.localeCompare(b.name));
+      this.filteredAdapters = this.adapterFilter.transform(this.existingAdapters, this.currentFilter);
+      this.dataSource = new MatTableDataSource(this.filteredAdapters);
+      setTimeout(() => {
+        this.dataSource.paginator = this.paginator;
+        this.dataSource.sort = this.sort;
+      });
+    });
+  }
+
+  createNewAdapter(): void {
+    this.router.navigate(['connect', 'create']);
+  }
+
+  applyFilter(filter: AdapterFilterSettingsModel) {
+    this.currentFilter = filter;
+    if (this.dataSource) {
+      this.dataSource.data = this.adapterFilter.transform(this.filteredAdapters, this.currentFilter);
+    }
+  }
+
+}
diff --git a/ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.html b/ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.html
new file mode 100644
index 0000000..d6fc0b5
--- /dev/null
+++ b/ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.html
@@ -0,0 +1,48 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="row" fxFlex="100">
+
+    <div class="data-marketplace-options-item pl-5 form-style" fxLayoutAlign="start center"
+         fxLayout="row">
+        <mat-icon color="accent">search</mat-icon>
+        <mat-form-field class="form-style" color="accent" floatLabel="never">
+            <input matInput placeholder="Find Element" value="" (input)="updateFilterTerm($event.target.value)"
+                   name="something">
+        </mat-form-field>
+    </div>
+    <div class="data-marketplace-options-item">
+        <mat-form-field color="accent">
+            <mat-select [(value)]="currentFilter.selectedType" (selectionChange)="filterAdapter($event)">
+                <mat-option *ngFor="let type of adapterTypes" [value]="type">
+                    {{type}}
+                </mat-option>
+            </mat-select>
+        </mat-form-field>
+    </div>
+    <div class="data-marketplace-options-item">
+        <mat-form-field color="accent">
+            <mat-select [(value)]="currentFilter.selectedCategory" (selectionChange)="filterAdapter($event)">
+                <mat-option *ngFor="let category of adapterCategories" [value]="category.code">
+                    {{category.label}}
+                </mat-option>
+            </mat-select>
+        </mat-form-field>
+    </div>
+    <span fxFlex></span>
+</div>
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss b/ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.scss
similarity index 60%
copy from ui/src/app/connect/components/format-item-json/format-item-json.component.scss
copy to ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.scss
index 30123c0..c239b47 100644
--- a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
+++ b/ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.scss
@@ -16,32 +16,33 @@
  *
  */
 
-
-.format-label {
-  line-height:50px;
-  margin: auto;
-  text-align: center;
-  font-weight: bold;
-  font-size: 1.3em;
+::ng-deep .mat-select-panel {
+  background: #fff;
 }
 
-.format-box {
-  min-height: 50px;
-  box-shadow: 1px 1px 2px #555;
-  border: 1px solid gray;
-  cursor: pointer;
-  padding: 10px;
-  opacity: 0.7;
-  margin: 10px;
-  background: #ffffff;
+::ng-deep .mat-select-panel:not([class*=mat-elevation-z]) {
+  box-shadow: 0 2px 4px -1px rgba(0,0,0,.2), 0 4px 5px 0 rgba(0,0,0,.14), 0 1px 10px 0 rgba(0,0,0,.12);
 }
 
-.format-box:hover {
-  opacity: 1;
+#categoryFilter {
+  margin-top: 20px;
 }
 
-.selectedItem {
-  opacity: 1;
-  background-color: grey;
+.data-marketplace-options {
+  padding:0px;
+  background-color: var(--color-bg-1);
+  border-bottom: 1px solid var(--color-bg-3);
 }
 
+.data-marketplace-options-item {
+  display: inline;
+  margin-right: 10px;
+}
+
+.form-style {
+  margin: 0px 5px 0px 0px;
+}
+
+.fixed-height {
+  height: 50px;
+}
diff --git a/ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.ts b/ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.ts
new file mode 100644
index 0000000..7e67e7d
--- /dev/null
+++ b/ui/src/app/connect/components/filter-toolbar/filter-toolbar.component.ts
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { AdapterService } from '@streampipes/platform-services';
+import { MatSelectChange } from '@angular/material/select';
+import { AdapterFilterSettingsModel } from '../../model/adapter-filter-settings.model';
+
+@Component({
+  selector: 'sp-connect-filter-toolbar',
+  templateUrl: './filter-toolbar.component.html',
+  styleUrls: ['./filter-toolbar.component.scss']
+})
+export class SpConnectFilterToolbarComponent implements OnInit {
+
+  @Output()
+  filterChangedEmitter: EventEmitter<AdapterFilterSettingsModel> = new EventEmitter<AdapterFilterSettingsModel>();
+
+  adapterTypes: string[] = ['All types', 'Data Set', 'Data Stream'];
+  adapterCategories: any;
+
+  currentFilter: AdapterFilterSettingsModel = {textFilter: '', selectedCategory: 'All', selectedType: 'All types'};
+
+  constructor(private dataMarketplaceService: AdapterService) {
+
+  }
+
+  ngOnInit(): void {
+    this.loadAvailableTypeCategories();
+  }
+
+  loadAvailableTypeCategories() {
+    this.dataMarketplaceService.getAdapterCategories().subscribe(res => {
+      this.adapterCategories = res;
+      this.adapterCategories.unshift({ label: 'All categories', description: '', code: 'All' });
+      this.filterChangedEmitter.emit(this.currentFilter);
+    });
+  }
+
+  filterAdapter(event: MatSelectChange) {
+    this.filterChangedEmitter.emit(this.currentFilter);
+  }
+
+  updateFilterTerm(event: string) {
+    this.currentFilter.textFilter = event;
+    this.filterChangedEmitter.emit(this.currentFilter);
+  }
+
+
+}
diff --git a/ui/src/app/connect/components/format-configuration/format-configuration.component.html b/ui/src/app/connect/components/format-configuration/format-configuration.component.html
deleted file mode 100644
index 13da938..0000000
--- a/ui/src/app/connect/components/format-configuration/format-configuration.component.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div style="margin-bottom: 2%;">
-
-    <div class="assemblyOptions sp-blue-bg">
-        <h4>Select format</h4>
-    </div>
-    <div class="sp-blue-border padding">
-        <sp-format-list fxFlex="100"
-                        (selectedFormatEmitter)="formatSelected($event)"
-                        [selectedFormat]="selectedFormat">
-        </sp-format-list>
-    </div>
-
-    <div class="assemblyOptions sp-blue-bg"
-         *ngIf="selectedFormat">
-        <h4>Configure format</h4>
-    </div>
-
-    <div *ngIf="selectedFormat">
-        <div *ngIf="selectedFormat.config.length > 0">
-            <sp-configuration-group
-                    [configurationGroup]="formatForm"
-                    [adapterId]="adapterDescription.appId"
-                    [configuration]="selectedFormat.config">
-            </sp-configuration-group>
-        </div>
-
-        <div *ngIf="selectedFormat.config.length === 0" class="sp-blue-border padding" style="padding: 15px;">
-            <div  style="text-align:center;">
-                <h5 >(no further configuration needed)</h5>
-            </div>
-        </div>
-    </div>
-</div>
-
-<div fxLayoutAlign="end">
-    <button class="mat-basic" mat-raised-button (click)="removeSelection()">Cancel</button>
-    <button class="mat-basic stepper-button" mat-raised-button (click)="goBack()">Back</button>
-    <button class="stepper-button"
-            id="format-selection-next-button"
-            data-cy="sp-format-selection-next-button"
-            [disabled]="!formatConfigurationValid"
-            (click)="clickNext()"
-            color="accent" mat-raised-button>
-        Next
-    </button>
-</div>
-
diff --git a/ui/src/app/connect/components/generic-adapter-configuration/generic-adapter-configuration.component.html b/ui/src/app/connect/components/generic-adapter-configuration/generic-adapter-configuration.component.html
deleted file mode 100644
index 5e1418c..0000000
--- a/ui/src/app/connect/components/generic-adapter-configuration/generic-adapter-configuration.component.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div style="margin-bottom: 2%;">
-
-    <div >
-        <div class="assemblyOptions sp-blue-bg">
-            <h4 >Protocol settings</h4>
-        </div>
-
-        <sp-configuration-group
-                [configurationGroup]="genericAdapterForm"
-                [adapterId]="adapterDescription.appId"
-                [configuration]="protocolDescription.config">
-        </sp-configuration-group>
-    </div>
-</div>
-
-<div fxLayoutAlign="end">
-    <button class="mat-basic" mat-raised-button (click)="removeSelection()">Cancel</button>
-    <div id="generic-settings-next-button">
-        <button class="stepper-button" [disabled]="!genericAdapterSettingsFormValid"
-                (click)="clickNext()" color="accent" mat-raised-button>Next
-        </button>
-    </div>
-</div>
diff --git a/ui/src/app/connect/components/generic-adapter-configuration/generic-adapter-configuration.component.ts b/ui/src/app/connect/components/generic-adapter-configuration/generic-adapter-configuration.component.ts
deleted file mode 100644
index 5746201..0000000
--- a/ui/src/app/connect/components/generic-adapter-configuration/generic-adapter-configuration.component.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import {
-  AdapterDescriptionUnion,
-  GenericAdapterSetDescription,
-  GenericAdapterStreamDescription,
-  ProtocolDescription
-} from '@streampipes/platform-services';
-import { FormBuilder, FormGroup } from '@angular/forms';
-import { MatStepper } from '@angular/material/stepper';
-
-@Component({
-  selector: 'sp-generic-adapter-configuration',
-  templateUrl: './generic-adapter-configuration.component.html',
-  styleUrls: ['./generic-adapter-configuration.component.scss']
-})
-export class GenericAdapterConfigurationComponent implements OnInit {
-
-  /**
-   * Adapter description the selected format is added to
-   */
-  @Input() adapterDescription: AdapterDescriptionUnion;
-
-  /**
-   * Cancels the adapter configuration process
-   */
-  @Output() removeSelectionEmitter: EventEmitter<boolean> = new EventEmitter();
-
-  /**
-   * Go to next configuration step when this is complete
-   */
-  @Output() clickNextEmitter: EventEmitter<MatStepper> = new EventEmitter();
-
-
-  genericAdapterSettingsFormValid: boolean;
-
-  genericAdapterForm: FormGroup;
-
-  protocolDescription: ProtocolDescription;
-
-  constructor(
-    private _formBuilder: FormBuilder
-  ) { }
-
-  ngOnInit(): void {
-
-    if (this.adapterDescription instanceof GenericAdapterSetDescription ||
-      this.adapterDescription instanceof GenericAdapterStreamDescription) {
-      this.protocolDescription = this.adapterDescription.protocolDescription;
-    }
-
-    // initialize form for validation
-    this.genericAdapterForm = this._formBuilder.group({});
-    this.genericAdapterForm.statusChanges.subscribe((status) => {
-      this.genericAdapterSettingsFormValid = this.genericAdapterForm.valid;
-    });
-  }
-
-  public removeSelection() {
-    this.removeSelectionEmitter.emit();
-  }
-
-  public clickNext() {
-    this.clickNextEmitter.emit();
-  }
-}
diff --git a/ui/src/app/connect/components/new-adapter/adapter-configuration.directive.ts b/ui/src/app/connect/components/new-adapter/adapter-configuration.directive.ts
new file mode 100644
index 0000000..b5ba397
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/adapter-configuration.directive.ts
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Directive, EventEmitter, Input, Output } from '@angular/core';
+import { MatStepper } from '@angular/material/stepper';
+import {
+  AdapterDescriptionUnion,
+  PipelineElementTemplate,
+  PipelineElementTemplateService
+} from '@streampipes/platform-services';
+import { FormBuilder } from '@angular/forms';
+import { AdapterTemplateService } from '../../services/adapter-template.service';
+import { DialogService } from '@streampipes/shared-ui';
+
+@Directive()
+export abstract class AdapterConfigurationDirective {
+
+  /**
+   * Adapter description the selected format is added to
+   */
+  @Input() adapterDescription: AdapterDescriptionUnion;
+
+  cachedAdapterDescription: AdapterDescriptionUnion;
+
+  /**
+   * Cancels the adapter configuration process
+   */
+  @Output() removeSelectionEmitter: EventEmitter<boolean> = new EventEmitter();
+
+  /**
+   * Go to next configuration step when this is complete
+   */
+  @Output() clickNextEmitter: EventEmitter<MatStepper> = new EventEmitter();
+
+  @Output() updateAdapterDescriptionEmitter: EventEmitter<AdapterDescriptionUnion> = new EventEmitter<AdapterDescriptionUnion>();
+
+  availableTemplates: PipelineElementTemplate[];
+  selectedTemplate: any = false;
+
+  constructor(protected _formBuilder: FormBuilder,
+              protected dialogService: DialogService,
+              protected pipelineElementTemplateService: PipelineElementTemplateService,
+              protected adapterTemplateService: AdapterTemplateService) {
+  }
+
+  onInit(): void {
+    this.loadPipelineElementTemplates();
+  }
+
+  public removeSelection() {
+    this.removeSelectionEmitter.emit();
+  }
+
+  public clickNext() {
+    this.clickNextEmitter.emit();
+  }
+
+  loadPipelineElementTemplates() {
+    this.pipelineElementTemplateService
+      .getPipelineElementTemplates(this.adapterDescription.appId)
+      .subscribe(templates => {
+        this.availableTemplates = templates;
+      });
+  }
+
+  loadTemplate(event: any) {
+    if (!event.value) {
+      this.adapterDescription = {...this.cachedAdapterDescription};
+      this.selectedTemplate = false;
+    } else {
+      this.selectedTemplate = event.value;
+      this.pipelineElementTemplateService.getConfiguredAdapterForTemplate(event.value._id, this.adapterDescription)
+        .subscribe(adapterDescription => {
+          this.afterTemplateReceived(adapterDescription);
+        });
+    }
+  }
+
+  abstract openTemplateDialog(): void;
+
+  abstract afterTemplateReceived(adapterDescription: any);
+
+}
diff --git a/ui/src/app/connect/components/new-adapter/format-configuration/format-configuration.component.html b/ui/src/app/connect/components/new-adapter/format-configuration/format-configuration.component.html
new file mode 100644
index 0000000..7a998c5
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/format-configuration/format-configuration.component.html
@@ -0,0 +1,58 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column">
+    <sp-basic-inner-panel panelTitle="Select format" outerMargin="20px 0px">
+        <sp-format-list fxFlex="100"
+                        (selectedFormatEmitter)="formatSelected($event)"
+                        [selectedFormat]="selectedFormat">
+        </sp-format-list>
+    </sp-basic-inner-panel>
+
+    <sp-basic-inner-panel panelTitle="Configure Format" outerMargin="10px 0px 20px 0px" *ngIf="selectedFormat">
+
+        <div *ngIf="selectedFormat">
+            <div *ngIf="selectedFormat.config.length > 0">
+                <sp-configuration-group
+                        [configurationGroup]="formatForm"
+                        [adapterId]="adapterDescription.appId"
+                        [configuration]="selectedFormat.config">
+                </sp-configuration-group>
+            </div>
+
+            <div *ngIf="selectedFormat.config.length === 0" style="padding: 15px;">
+                <div style="text-align:center;">
+                    <h5>(no further configuration needed)</h5>
+                </div>
+            </div>
+        </div>
+    </sp-basic-inner-panel>
+
+    <div fxLayoutAlign="end">
+        <button class="mat-basic" mat-raised-button (click)="removeSelection()">Cancel</button>
+        <button class="mat-basic stepper-button" mat-raised-button (click)="goBack()">Back</button>
+        <button class="stepper-button"
+                id="format-selection-next-button"
+                data-cy="sp-format-selection-next-button"
+                [disabled]="!formatConfigurationValid"
+                (click)="clickNext()"
+                color="accent" mat-raised-button>
+            Next
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/format-configuration/format-configuration.component.scss b/ui/src/app/connect/components/new-adapter/format-configuration/format-configuration.component.scss
similarity index 100%
rename from ui/src/app/connect/components/format-configuration/format-configuration.component.scss
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-configuration.component.scss
diff --git a/ui/src/app/connect/components/format-configuration/format-configuration.component.ts b/ui/src/app/connect/components/new-adapter/format-configuration/format-configuration.component.ts
similarity index 98%
rename from ui/src/app/connect/components/format-configuration/format-configuration.component.ts
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-configuration.component.ts
index 87a8c7c..b129651 100644
--- a/ui/src/app/connect/components/format-configuration/format-configuration.component.ts
+++ b/ui/src/app/connect/components/new-adapter/format-configuration/format-configuration.component.ts
@@ -24,7 +24,7 @@
   GenericAdapterStreamDescription
 } from '@streampipes/platform-services';
 import { FormBuilder, FormGroup } from '@angular/forms';
-import { RestService } from '../../services/rest.service';
+import { RestService } from '../../../services/rest.service';
 import { MatStepper } from '@angular/material/stepper';
 
 @Component({
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.html b/ui/src/app/connect/components/new-adapter/format-configuration/format-item-json/format-item-json.component.html
similarity index 100%
rename from ui/src/app/connect/components/format-item-json/format-item-json.component.html
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-item-json/format-item-json.component.html
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss b/ui/src/app/connect/components/new-adapter/format-configuration/format-item-json/format-item-json.component.scss
similarity index 94%
rename from ui/src/app/connect/components/format-item-json/format-item-json.component.scss
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-item-json/format-item-json.component.scss
index 30123c0..2d626c4 100644
--- a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
+++ b/ui/src/app/connect/components/new-adapter/format-configuration/format-item-json/format-item-json.component.scss
@@ -42,6 +42,7 @@
 
 .selectedItem {
   opacity: 1;
-  background-color: grey;
+  background-color: var(--color-accent);
+  color: var(--color-bg-2);
 }
 
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.ts b/ui/src/app/connect/components/new-adapter/format-configuration/format-item-json/format-item-json.component.ts
similarity index 100%
rename from ui/src/app/connect/components/format-item-json/format-item-json.component.ts
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-item-json/format-item-json.component.ts
diff --git a/ui/src/app/connect/components/format-item/format-item.component.html b/ui/src/app/connect/components/new-adapter/format-configuration/format-item/format-item.component.html
similarity index 100%
rename from ui/src/app/connect/components/format-item/format-item.component.html
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-item/format-item.component.html
diff --git a/ui/src/app/connect/components/format-item/format-item.component.scss b/ui/src/app/connect/components/new-adapter/format-configuration/format-item/format-item.component.scss
similarity index 94%
rename from ui/src/app/connect/components/format-item/format-item.component.scss
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-item/format-item.component.scss
index db43ef1..3aa1b93 100644
--- a/ui/src/app/connect/components/format-item/format-item.component.scss
+++ b/ui/src/app/connect/components/new-adapter/format-configuration/format-item/format-item.component.scss
@@ -41,5 +41,6 @@
 
 .selectedItem {
   opacity: 1;
-  background-color: grey;
+  background-color: var(--color-accent);
+  color: var(--color-bg-2);
 }
diff --git a/ui/src/app/connect/components/format-item/format-item.component.ts b/ui/src/app/connect/components/new-adapter/format-configuration/format-item/format-item.component.ts
similarity index 95%
rename from ui/src/app/connect/components/format-item/format-item.component.ts
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-item/format-item.component.ts
index 6d7db60..77f2662 100644
--- a/ui/src/app/connect/components/format-item/format-item.component.ts
+++ b/ui/src/app/connect/components/new-adapter/format-configuration/format-item/format-item.component.ts
@@ -17,7 +17,7 @@
  */
 
 import { Component, EventEmitter, Input, Output } from '@angular/core';
-import { ShepherdService } from '../../../services/tour/shepherd.service';
+import { ShepherdService } from '../../../../../services/tour/shepherd.service';
 import { FormatDescription } from '@streampipes/platform-services';
 
 @Component({
diff --git a/ui/src/app/connect/components/format-list/format-list.component.html b/ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.html
similarity index 95%
rename from ui/src/app/connect/components/format-list/format-list.component.html
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.html
index 59d46c2..81eefc0 100644
--- a/ui/src/app/connect/components/format-list/format-list.component.html
+++ b/ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.html
@@ -33,9 +33,9 @@
     </div>
 
     <div fxFlex="100"
-         class="assemblyOptions sp-blue-bg"
+         class="format-title"
          *ngIf="selectJsonFormats">
-        <h4>Select json format</h4>
+        <h4>Select JSON format</h4>
     </div>
 
     <div fxFlex="25"
diff --git a/ui/src/app/connect/components/format-list/format-list.component.scss b/ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.scss
similarity index 78%
rename from ui/src/app/connect/components/format-list/format-list.component.scss
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.scss
index 9db395a..61c683a 100644
--- a/ui/src/app/connect/components/format-list/format-list.component.scss
+++ b/ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.scss
@@ -17,6 +17,16 @@
  */
 
 .fullWidth {
-    width: 100%;
-    height: 100%;
-  }
\ No newline at end of file
+  width: 100%;
+  height: 100%;
+}
+
+.format-title {
+  margin-top: 10px;
+  margin-left: 5px;
+  padding-left: 5px;
+  border-left: 4px solid var(--color-accent);
+  font-weight: 600;
+  font-size: 13pt;
+  white-space: nowrap;
+}
diff --git a/ui/src/app/connect/components/format-list/format-list.component.ts b/ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.ts
similarity index 97%
rename from ui/src/app/connect/components/format-list/format-list.component.ts
rename to ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.ts
index bcc1afd..65d18a4 100644
--- a/ui/src/app/connect/components/format-list/format-list.component.ts
+++ b/ui/src/app/connect/components/new-adapter/format-configuration/format-list/format-list.component.ts
@@ -18,7 +18,7 @@
 
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { FormatDescription } from '@streampipes/platform-services';
-import { RestService } from '../../services/rest.service';
+import { RestService } from '../../../../services/rest.service';
 
 @Component({
     selector: 'sp-format-list',
diff --git a/ui/src/app/connect/components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component.html b/ui/src/app/connect/components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component.html
new file mode 100644
index 0000000..9dd1a3d
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component.html
@@ -0,0 +1,63 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column">
+    <div fxFlex="100" fxLayout="column">
+        <div fxFlex="100" fxLayout="column">
+            <sp-basic-inner-panel panelTitle="Protocol Settings" outerMargin="20px 0px">
+                <div header fxFlex="100" fxLayout="row" fxLayoutAlign="end center" class="pr-5">
+                    <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center"
+                         *ngIf="availableTemplates && availableTemplates.length > 0">
+                        <mat-form-field class="form-field" floatLabel="never" color="accent">
+                            <mat-label>Use template</mat-label>
+                            <mat-select (selectionChange)="loadTemplate($event)"
+                                        [(value)]="selectedTemplate">
+                                <mat-option>--</mat-option>
+                                <mat-option [value]="template" *ngFor="let template of availableTemplates">
+                                    {{template.templateName}}
+                                </mat-option>
+                            </mat-select>
+                        </mat-form-field>
+                    </div>
+                </div>
+                <sp-configuration-group
+                        [configurationGroup]="genericAdapterForm"
+                        [adapterId]="adapterDescription.appId"
+                        [configuration]="protocolDescription.config">
+                </sp-configuration-group>
+            </sp-basic-inner-panel>
+        </div>
+    </div>
+
+    <div fxLayoutAlign="end">
+        <button class="mat-basic"
+                mat-raised-button
+                (click)="removeSelection()"
+                style="margin-right: 10px;">Cancel
+        </button>
+        <button mat-button mat-raised-button
+                class="mat-basic"
+                (click)="openTemplateDialog()">Store config as template
+        </button>
+        <div id="generic-settings-next-button">
+            <button class="stepper-button" [disabled]="!genericAdapterSettingsFormValid"
+                    (click)="clickNext()" color="accent" mat-raised-button>Next
+            </button>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/generic-adapter-configuration/generic-adapter-configuration.component.scss b/ui/src/app/connect/components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component.scss
similarity index 100%
rename from ui/src/app/connect/components/generic-adapter-configuration/generic-adapter-configuration.component.scss
rename to ui/src/app/connect/components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component.scss
diff --git a/ui/src/app/connect/components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component.ts b/ui/src/app/connect/components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component.ts
new file mode 100644
index 0000000..80b9301
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component.ts
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import {
+  GenericAdapterSetDescription,
+  GenericAdapterStreamDescription,
+  ProtocolDescription,
+  PipelineElementTemplateService
+} from '@streampipes/platform-services';
+import { FormBuilder, FormGroup } from '@angular/forms';
+import { AdapterConfigurationDirective } from '../adapter-configuration.directive';
+import { AdapterTemplateService } from '../../../services/adapter-template.service';
+import { DialogService } from '@streampipes/shared-ui';
+
+@Component({
+  selector: 'sp-generic-adapter-configuration',
+  templateUrl: './generic-adapter-configuration.component.html',
+  styleUrls: ['./generic-adapter-configuration.component.scss']
+})
+export class GenericAdapterConfigurationComponent extends AdapterConfigurationDirective implements OnInit {
+
+  genericAdapterSettingsFormValid: boolean;
+
+  genericAdapterForm: FormGroup;
+
+  protocolDescription: ProtocolDescription;
+
+  constructor(_formBuilder: FormBuilder,
+              dialogService: DialogService,
+              pipelineElementTemplateService: PipelineElementTemplateService,
+              adapterTemplateService: AdapterTemplateService) {
+    super(_formBuilder, dialogService, pipelineElementTemplateService, adapterTemplateService);
+  }
+
+  ngOnInit(): void {
+    super.onInit();
+    if (this.adapterDescription instanceof GenericAdapterSetDescription ||
+      this.adapterDescription instanceof GenericAdapterStreamDescription) {
+      this.protocolDescription = this.adapterDescription.protocolDescription;
+    }
+
+    // initialize form for validation
+    this.genericAdapterForm = this._formBuilder.group({});
+    this.genericAdapterForm.statusChanges.subscribe((status) => {
+      this.genericAdapterSettingsFormValid = this.genericAdapterForm.valid;
+    });
+  }
+
+  openTemplateDialog(): void {
+    const dialogRef = this.adapterTemplateService.getDialog(this.protocolDescription.config, this.protocolDescription.appId);
+
+    dialogRef.afterClosed().subscribe(refresh => {
+      this.loadPipelineElementTemplates();
+    });
+  }
+
+  afterTemplateReceived(adapterDescription: any) {
+    this.protocolDescription = ProtocolDescription.fromData(adapterDescription.protocolDescription);
+    if (this.adapterDescription instanceof GenericAdapterSetDescription ||
+      this.adapterDescription instanceof GenericAdapterStreamDescription) {
+      this.adapterDescription.protocolDescription = this.protocolDescription;
+      this.updateAdapterDescriptionEmitter.emit(this.adapterDescription);
+    }
+  }
+
+}
diff --git a/ui/src/app/connect/components/new-adapter/new-adapter.component.html b/ui/src/app/connect/components/new-adapter/new-adapter.component.html
index c2777ee..9c1a1ae 100644
--- a/ui/src/app/connect/components/new-adapter/new-adapter.component.html
+++ b/ui/src/app/connect/components/new-adapter/new-adapter.component.html
@@ -16,80 +16,85 @@
   ~
   -->
 
-<div fxLayout="column" fxLayoutAlign="center stretch">
-    <div fxLayout="column" fxFlex="100" class="p-10">
-        <div fxLayout="row" fxLayoutAlign="start center">
-            <mat-icon *ngIf="isDataSetDescription" class="historic">lens</mat-icon>
-            <mat-icon *ngIf="isDataStreamDescription" class="real-time">lens
-            </mat-icon>
-            <div fxLayoutAlign="start center">
-                <p *ngIf="isDataSetDescription">Data Set</p>
-                <p *ngIf="isDataStreamDescription">Data Stream</p>
-            </div>
-            <span fxFlex></span>
-            <div fxLayoutAlign="end start">
-                <button mat-icon-button (click)="removeSelection()">
-                    <i class="material-icons">close</i>
-                </button>
-            </div>
-        </div>
-        <h1 *ngIf="!fromTemplate" class="new-adapter-title">New Source: {{adapter.templateTitle}}</h1>
-        <h1 *ngIf="fromTemplate" class="new-adapter-title">From Template: {{adapter.templateTitle}}</h1>
+<sp-basic-view [padding]="true" [showBackLink]="false">
+
+    <div nav fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
+        <button mat-icon-button (click)="removeSelection()" matTooltip="Cancel">
+            <i class="material-icons">close</i>
+        </button>
     </div>
+    <div fxLayout="column" fxLayoutAlign="center stretch" *ngIf="adapter">
+        <div fxLayout="column" fxFlex="100">
+            <div fxLayout="row" fxLayoutAlign="start center">
+                <mat-icon *ngIf="isDataSetDescription" class="historic">lens</mat-icon>
+                <mat-icon *ngIf="isDataStreamDescription" class="real-time">lens
+                </mat-icon>
+                <div fxLayoutAlign="start center">
+                    <p *ngIf="isDataSetDescription">Data Set</p>
+                    <p *ngIf="isDataStreamDescription">Data Stream</p>
+                </div>
+                <span fxFlex></span>
+            </div>
+            <h1 *ngIf="!fromTemplate" class="new-adapter-title">New Source: {{adapter.templateTitle}}</h1>
+            <h1 *ngIf="fromTemplate" class="new-adapter-title">From Template: {{adapter.templateTitle}}</h1>
+        </div>
 
-    <mat-horizontal-stepper [linear]="true" #stepper color="accent" class="stepper">
-        <mat-step *ngIf="!isGenericAdapter">
-            <ng-template matStepLabel>Settings</ng-template>
-            <sp-specific-adapter-configuration
-                    [adapterDescription]="adapter"
-                    (clickNextEmitter)="clickSpecificSettingsNextButton()"
-                    (removeSelectionEmitter)="removeSelection()">
-            </sp-specific-adapter-configuration>
-        </mat-step>
+        <mat-horizontal-stepper [linear]="true" #stepper color="accent" class="stepper">
+            <mat-step *ngIf="!isGenericAdapter">
+                <ng-template matStepLabel>Settings</ng-template>
+                <sp-specific-adapter-configuration
+                        [adapterDescription]="adapter"
+                        (updateAdapterDescriptionEmitter)="adapter = $event"
+                        (clickNextEmitter)="clickSpecificSettingsNextButton()"
+                        (removeSelectionEmitter)="removeSelection()">
+                </sp-specific-adapter-configuration>
+            </mat-step>
 
-        <mat-step *ngIf="isGenericAdapter">
-            <ng-template matStepLabel>Settings</ng-template>
-            <sp-generic-adapter-configuration
-                    [adapterDescription]="adapter"
-                    (clickNextEmitter)="clickProtocolSettingsNextButton()"
-                    (removeSelectionEmitter)="removeSelection()">
-            </sp-generic-adapter-configuration>
-        </mat-step>
+            <mat-step *ngIf="isGenericAdapter">
+                <ng-template matStepLabel>Settings</ng-template>
+                <sp-generic-adapter-configuration
+                        [adapterDescription]="adapter"
+                        (updateAdapterDescriptionEmitter)="adapter = $event"
+                        (clickNextEmitter)="clickProtocolSettingsNextButton()"
+                        (removeSelectionEmitter)="removeSelection()">
+                </sp-generic-adapter-configuration>
+            </mat-step>
 
-        <mat-step *ngIf="isGenericAdapter">
-            <ng-template matStepLabel>Select Format</ng-template>
-            <sp-format-configuration
-                    [adapterDescription]="adapter"
-                    (clickNextEmitter)="clickFormatSelectionNextButton()"
-                    (goBackEmitter)="goBack()"
-                    (removeSelectionEmitter)="removeSelection()">
-            </sp-format-configuration>
-        </mat-step>
+            <mat-step *ngIf="isGenericAdapter">
+                <ng-template matStepLabel>Select Format</ng-template>
+                <sp-format-configuration
+                        [adapterDescription]="adapter"
+                        (clickNextEmitter)="clickFormatSelectionNextButton()"
+                        (goBackEmitter)="goBack()"
+                        (removeSelectionEmitter)="removeSelection()">
+                </sp-format-configuration>
+            </mat-step>
 
-        <mat-step>
-            <ng-template matStepLabel>Define Event Schema</ng-template>
-            <sp-event-schema #eschema fxLayout="column" fxFlex="100"
-                             [(isEditable)]="isEditable"
-                             [adapterDescription]="adapter"
-                             [(eventSchema)]="eventSchema"
-                             [(oldEventSchema)]="oldEventSchema"
-                             (clickNextEmitter)="clickEventSchemaNextButtonButton()"
-                             (goBackEmitter)="goBack()"
-                             (removeSelectionEmitter)="removeSelection()">
-            </sp-event-schema>
-        </mat-step>
+            <mat-step>
+                <ng-template matStepLabel>Configure fields</ng-template>
+                <sp-event-schema #eschema fxLayout="column" fxFlex="100"
+                                 [(isEditable)]="isEditable"
+                                 [adapterDescription]="adapter"
+                                 [(eventSchema)]="eventSchema"
+                                 [(oldEventSchema)]="oldEventSchema"
+                                 (clickNextEmitter)="clickEventSchemaNextButtonButton()"
+                                 (goBackEmitter)="goBack()"
+                                 (removeSelectionEmitter)="removeSelection()">
+                </sp-event-schema>
+            </mat-step>
 
-        <mat-step>
-            <ng-template matStepLabel>Start Adapter</ng-template>
-            <sp-start-adapter-configuration
-                    [adapterDescription]="adapter"
-                    [eventSchema]="eventSchema"
-                    (removeSelectionEmitter)="removeSelection()"
-                    (goBackEmitter)="goBack()"
-                    (adapterStartedEmitter)="adapterWasStarted()">
-            </sp-start-adapter-configuration>
-        </mat-step>
+            <mat-step>
+                <ng-template matStepLabel>Start Adapter</ng-template>
+                <sp-start-adapter-configuration
+                        [adapterDescription]="adapter"
+                        [eventSchema]="eventSchema"
+                        (removeSelectionEmitter)="removeSelection()"
+                        (goBackEmitter)="goBack()"
+                        (adapterStartedEmitter)="adapterWasStarted()">
+                </sp-start-adapter-configuration>
+            </mat-step>
 
-    </mat-horizontal-stepper>
+        </mat-horizontal-stepper>
 
-</div>
+    </div>
+</sp-basic-view>
diff --git a/ui/src/app/connect/components/new-adapter/new-adapter.component.ts b/ui/src/app/connect/components/new-adapter/new-adapter.component.ts
index 1b593b5..2a0566e 100644
--- a/ui/src/app/connect/components/new-adapter/new-adapter.component.ts
+++ b/ui/src/app/connect/components/new-adapter/new-adapter.component.ts
@@ -16,25 +16,29 @@
  *
  */
 
-import { AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
+import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, ViewChild } from '@angular/core';
 import { FormBuilder, FormGroup } from '@angular/forms';
 import { MatStepper } from '@angular/material/stepper';
 import {
-    AdapterDescriptionUnion,
-    EventSchema,
-    GenericAdapterSetDescription,
-    GenericAdapterStreamDescription,
-    SpecificAdapterSetDescription,
-    SpecificAdapterStreamDescription,
-    TransformationRuleDescriptionUnion
+  AdapterDescriptionUnion,
+  AdapterService,
+  EventSchema,
+  GenericAdapterSetDescription,
+  GenericAdapterStreamDescription,
+  SpecificAdapterSetDescription,
+  SpecificAdapterStreamDescription,
+  TransformationRuleDescriptionUnion
 } from '@streampipes/platform-services';
 import { ShepherdService } from '../../../services/tour/shepherd.service';
 import { ConnectService } from '../../services/connect.service';
 import { ConfigurationInfo } from '../../model/ConfigurationInfo';
 import { RestService } from '../../services/rest.service';
-import { EventSchemaComponent } from '../schema-editor/event-schema/event-schema.component';
+import { EventSchemaComponent } from './schema-editor/event-schema/event-schema.component';
 import { TransformationRuleService } from '../../services/transformation-rule.service';
 import { IconService } from '../../services/icon.service';
+import { ActivatedRoute, Router } from '@angular/router';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpConnectRoutes } from '../../connect.routes';
 
 @Component({
   selector: 'sp-new-adapter',
@@ -54,15 +58,7 @@
   @Input()
   adapter: AdapterDescriptionUnion;
 
-  @Output()
-  removeSelectionEmitter: EventEmitter<void> = new EventEmitter<void>();
-
-  @Output()
-  updateAdapterEmitter: EventEmitter<void> = new EventEmitter<void>();
-
-
-  @ViewChild('stepper', { static: true }) myStepper: MatStepper;
-
+  myStepper: MatStepper;
 
   protocolConfigurationValid: boolean;
   formatConfigurationValid: boolean;
@@ -79,10 +75,8 @@
   // deactivates all edit functions when user starts a template
   isEditable = true;
 
-  @ViewChild(EventSchemaComponent, { static: true })
   private eventSchemaComponent: EventSchemaComponent;
 
-
   completedStaticProperty: ConfigurationInfo;
 
   isPreviewEnabled = false;
@@ -98,7 +92,11 @@
     private connectService: ConnectService,
     private _formBuilder: FormBuilder,
     private iconService: IconService,
-    private changeDetectorRef: ChangeDetectorRef) {
+    private changeDetectorRef: ChangeDetectorRef,
+    private route: ActivatedRoute,
+    private dataMarketplaceService: AdapterService,
+    private router: Router,
+    private breadcrumbService: SpBreadcrumbService) {
   }
 
   handleFileInput(files: any) {
@@ -115,36 +113,45 @@
 
   ngOnInit() {
 
-    this.parentForm = this._formBuilder.group({});
+    this.dataMarketplaceService.getAdapterDescriptions().subscribe(adapters => {
+      const adapter = adapters.find(a => a.appId === this.route.snapshot.params.appId);
+      this.adapter = this.connectService.cloneAdapterDescription(adapter);
+      this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.makeRoute([SpConnectRoutes.BASE, SpConnectRoutes.CREATE], this.adapter.name));
+      (this.adapter as any).templateTitle = this.adapter.name;
+      this.adapter.name = '';
+      this.adapter.description = '';
+      this.parentForm = this._formBuilder.group({});
 
 
-    this.isGenericAdapter = this.connectService.isGenericDescription(this.adapter);
-    this.isDataSetDescription = this.connectService.isDataSetDescription(this.adapter);
-    this.isDataStreamDescription = this.connectService.isDataStreamDescription(this.adapter);
-    this.formatConfigurationValid = false;
+      this.isGenericAdapter = this.connectService.isGenericDescription(this.adapter);
+      this.isDataSetDescription = this.connectService.isDataSetDescription(this.adapter);
+      this.isDataStreamDescription = this.connectService.isDataStreamDescription(this.adapter);
+      this.formatConfigurationValid = false;
 
 
-    // this.startAdapterFormGroup = this._formBuilder.group({
-    //     startAdapterFormCtrl: ['', Validators.required]
-    // });
+      // this.startAdapterFormGroup = this._formBuilder.group({
+      //     startAdapterFormCtrl: ['', Validators.required]
+      // });
 
-    this.protocolConfigurationValid = false;
+      this.protocolConfigurationValid = false;
 
-    this.eventSchema = this.connectService.getEventSchema(this.adapter);
+      this.eventSchema = this.connectService.getEventSchema(this.adapter);
 
-    if (this.eventSchema.eventProperties.length > 0) {
+      if (this.eventSchema.eventProperties.length > 0) {
 
-      // Timeout is needed for stepper to work correctly. Without the stepper is frozen when initializing with
-      // step 2. Can be removed when a better solution is found.
-      setTimeout(() => {
-        this.goForward();
-        this.goForward();
-      }, 1);
+        // Timeout is needed for stepper to work correctly. Without the stepper is frozen when initializing with
+        // step 2. Can be removed when a better solution is found.
+        setTimeout(() => {
+          this.goForward();
+          this.goForward();
+        }, 1);
 
-      this.fromTemplate = true;
-      this.isEditable = false;
-      this.oldEventSchema = this.eventSchema;
-    }
+        this.fromTemplate = true;
+        this.isEditable = false;
+        this.oldEventSchema = this.eventSchema;
+      }
+    });
+
 
     // this.parentForm.statusChanges.subscribe((status) => {
     //     this.genericadapterSettingsFormValid  = this.viewInitialized && this.parentForm.valid;
@@ -159,7 +166,7 @@
 
 
   removeSelection() {
-    this.removeSelectionEmitter.emit();
+    this.router.navigate(['connect', 'create']);
   }
 
   clickProtocolSettingsNextButton() {
@@ -230,7 +237,14 @@
   }
 
   public adapterWasStarted() {
-    this.updateAdapterEmitter.emit();
-    this.removeSelectionEmitter.emit();
+    this.router.navigate(['connect']);
+  }
+
+  @ViewChild(EventSchemaComponent) set schemaComponent(eventSchemaComponent: EventSchemaComponent) {
+    this.eventSchemaComponent = eventSchemaComponent;
+  }
+
+  @ViewChild('stepper') set stepperComponent(stepperComponent: MatStepper) {
+    this.myStepper = stepperComponent;
   }
 }
diff --git a/ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html b/ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.html
similarity index 67%
copy from ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html
copy to ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.html
index 639fd6c..ecfdf15 100644
--- a/ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.html
@@ -16,11 +16,11 @@
   ~
   -->
 
-<div fxLayout="column" >
-    <div fxLayoutAlign="center">
-        <mat-spinner fxLayoutAlign="center" style="margin: 10px 0 5px 0" color="accent">Loading</mat-spinner>
+<div fxLayout="column" fxFlex="100">
+    <div fxLayout="row" fxLayoutAlign="center center" fxFlex="100">
+        <div fxLayoutAlign="start center" class="error-text">&nbsp;There was an error while guessing the schema of your configured data source:</div>
     </div>
-    <div fxLayoutAlign="center">
-        <h3>Guessing the event schema...</h3>
+    <div fxLayout="row" fxLayoutAlign="center center" class="mt-10">
+        <sp-exception-message [message]="errorMessage"></sp-exception-message>
     </div>
 </div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.scss
similarity index 91%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.scss
index 58ba04b..8eec370 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.scss
@@ -16,3 +16,10 @@
  *
  */
 
+.error-color {
+  color: #963e3e;
+}
+
+.error-text {
+  font-size: 12pt;
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts b/ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.ts
similarity index 86%
rename from ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
rename to ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.ts
index 4e64c25..b6dc01d 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/error-message/error-message.component.ts
@@ -18,6 +18,7 @@
 
 import { Component, Input, OnInit } from '@angular/core';
 import { Notification } from '@streampipes/platform-services';
+import { StreamPipesErrorMessage } from '../../../../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
 
 @Component({
   selector: 'sp-error-message',
@@ -26,7 +27,7 @@
 })
 export class ErrorMessageComponent implements OnInit {
 
-  @Input() errorMessages: Notification[];
+  @Input() errorMessage: StreamPipesErrorMessage;
 
   showErrorMessage = false;
 
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.html b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.html
new file mode 100644
index 0000000..cf07a44
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.html
@@ -0,0 +1,96 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="row" fxFlex="100" fxLayoutGap="10px">
+    <div fxLayout="row" fxLayoutAlign="start center">
+        <div>
+        <b style="white-space: nowrap">
+            {{ label }}
+        </b>
+        </div>
+        <div fxLayoutAlign="start center" *ngIf="originalRuntimeName" class="ml-5">
+            <span class="runtime-info">{{originalRuntimeName}}</span>
+            <span fxLayoutAlign="center center"
+                  *ngIf="originalRuntimeName !== node.data.runtimeName">
+                <i class="material-icons">arrow_right</i>
+            </span>
+            <span class="runtime-info"
+                  *ngIf="originalRuntimeName !== node.data.runtimeName">{{node.data.runtimeName}}
+            </span>
+        </div>
+        <p style="margin: 0px 10px 10px;" *ngIf="isList">[List]</p>
+    </div>
+
+    <div fxLayout="row" fxLayoutAlign="end center" fxFlex="100" fxLayoutGap="20px">
+        <div class="timestamp-property" *ngIf="timestampProperty" fxLayoutAlign="end center" fxLayout="row">
+            <mat-icon *ngIf="timestampProperty" class="timestamp-icon" fxLayout="row" fxLayoutAlign="start center">
+                access_time
+            </mat-icon>
+            <span style="margin-left: -5px;">marked as timestamp</span>
+        </div>
+        <div fxLayoutAlign="end center" class="runtime-type-info-outer">
+            <div fxLayout="row" fxLayoutAlign="start center" fxFlex="100" *ngIf="runtimeType" >
+            <span class="runtime-info runtime-type-info">{{originalRuntimeType}}</span>
+            <span fxLayoutAlign="center center" *ngIf="originalRuntimeType !== runtimeType"><i class="material-icons">arrow_right</i></span>
+            <span class="runtime-info runtime-type-info" *ngIf="originalRuntimeType !== runtimeType">{{runtimeType}}</span>
+            </div>
+        </div>
+        <div fxLayoutAlign="end center" class="status-outer">
+        <span *ngIf="showFieldStatus"
+              [ngClass]="'status status-' +fieldStatusInfo[originalRuntimeName].fieldStatus.toLowerCase()"
+              [matTooltip]="fieldStatusInfo[originalRuntimeName].additionalInfo">{{fieldStatusInfo[originalRuntimeName].fieldStatus}}</span>
+        </div>
+        <div *ngIf="isPrimitive" fxLayoutAlign="end center">
+            <mat-form-field class="small-select" color="accent">
+                <mat-select [(ngModel)]="node.data.propertyScope" panelClass="small-select"
+                            [attr.data-cy]="'property-scope-' + label">
+                    <mat-option value="MEASUREMENT_PROPERTY">Measurement</mat-option>
+                    <mat-option value="DIMENSION_PROPERTY">Dimension</mat-option>
+                    <mat-option value="HEADER_PROPERTY">Header</mat-option>
+                </mat-select>
+            </mat-form-field>
+        </div>
+
+        <div fxLayoutAlign="end center"
+             *ngIf="isNested">
+            <button [disabled]="!isEditable" color="accent" mat-button (click)=addNestedProperty(node.data)>
+                <mat-icon matTooltip="Add a Nested Property">queue</mat-icon>
+            </button>
+        </div>
+        <div
+                fxLayoutAlign="end center"
+                class="ml-5 mr-5"
+                *ngIf="isNested || isPrimitive || isList">
+            <button [disabled]="!isEditable" color="accent" mat-button
+                    (click)="openEditDialog(node.data)"
+                    [attr.data-cy]="'edit-' + label.toLowerCase()">
+                <mat-icon>edit</mat-icon>&nbsp;Edit field
+            </button>
+        </div>
+        <div fxLayoutAlign="end center">
+            <mat-checkbox
+                    *ngIf="isNested || isPrimitive || isList"
+                    (click)="selectProperty(node.data.id, undefined)"
+                    [disabled]="!isEditable"
+                    [class.checkbox-selected]="node.data.selected"
+                    [checked]="node.data.selected"
+                    [attr.data-cy]="'delete-property-' + label.toLowerCase()">
+            </mat-checkbox>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
new file mode 100644
index 0000000..ec24661
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background {
+  background-color: var(--color-accent) !important;
+}
+
+::ng-deep .mat-checkbox:not(.mat-checkbox-disabled).mat-accent .mat-checkbox-ripple .mat-ripple-element {
+  background-color: var(--color-accent) !important;
+}
+
+.checkbox-selected {
+  opacity: 1 !important;
+}
+
+.timestamp-property {
+  margin-left: 15px;
+  border-radius: 10px;
+  background: var(--color-processor);
+  padding: 0px 10px;
+  font-size: 12px;
+  color: #FFFFFF;
+}
+
+.timestamp-icon {
+  font-size: 12px;
+}
+
+.status-good {
+  background: #75c575;
+  color: white;
+}
+
+.status-bad {
+  background: #d2a169;
+  color: white;
+}
+
+.status {
+  width: 70px;
+  min-width: 70px;
+  text-align: center;
+  padding: 5px;
+  border-radius: 5px;
+}
+
+.status-outer {
+  width: 70px;
+  min-width: 70px;
+}
+
+.runtime-info {
+  border-radius: 5px;
+  color: var(--color-default-text);
+  font-size: 10pt;
+  text-align: center;
+}
+
+.runtime-type-info {
+  border-radius: 5px;
+  color: var(--color-default-text);
+  font-size: 10pt;
+  width: 70px;
+  border: 1px solid var(--color-bg-3);
+  text-align: center;
+}
+
+.runtime-type-info-outer {
+  padding: 3px;
+  border-radius: 5px;
+  width: 170px;
+  text-align: center;
+
+}
+
+
diff --git a/ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.ts b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.ts
similarity index 71%
rename from ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.ts
rename to ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.ts
index 4186a36..cd561af 100644
--- a/ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.ts
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.ts
@@ -21,30 +21,38 @@
 import { TreeNode } from '@circlon/angular-tree-component';
 import { MatDialog } from '@angular/material/dialog';
 import {
-    EventProperty,
-    EventPropertyList,
-    EventPropertyNested,
-    EventPropertyPrimitive,
-    EventPropertyUnion,
-    EventSchema
+  EventProperty,
+  EventPropertyList,
+  EventPropertyNested,
+  EventPropertyPrimitive,
+  EventPropertyUnion,
+  EventSchema,
+  FieldStatusInfo,
+  GuessTypeInfo
+
 } from '@streampipes/platform-services';
-import { EditEventPropertyComponent } from '../../../dialog/edit-event-property/edit-event-property.component';
+import { EditEventPropertyComponent } from '../../../../dialog/edit-event-property/edit-event-property.component';
+import { DialogService, PanelType } from '@streampipes/shared-ui';
 
 @Component({
   selector: 'event-property-row',
   templateUrl: './event-property-row.component.html',
   styleUrls: ['./event-property-row.component.scss']
 })
-export class EventPropertyRowComponent implements OnInit, OnChanges {
+export class EventPropertyRowComponent implements OnInit {
 
   @Input() node: TreeNode;
   @Input() isEditable = true;
   @Input() eventSchema: EventSchema = new EventSchema();
+  @Input() originalEventSchema: EventSchema;
   @Input() countSelected: number;
+  @Input() eventPreview: Record<string, GuessTypeInfo>[];
+  @Input() fieldStatusInfo: Record<string, FieldStatusInfo>;
 
   @Output() isEditableChange = new EventEmitter<boolean>();
   @Output() eventSchemaChange = new EventEmitter<EventSchema>();
-  @Output() refreshTreeEmitter = new EventEmitter<void>();
+  @Output() originalEventSchemaChange = new EventEmitter<EventSchema>();
+  @Output() refreshTreeEmitter = new EventEmitter<boolean>();
   @Output() countSelectedChange = new EventEmitter<number>();
 
   label: string;
@@ -52,8 +60,15 @@
   isNested = false;
   isList = false;
   timestampProperty = false;
+  showEventPreview = false;
+  showFieldStatus = false;
 
-  constructor(private dialog: MatDialog) {
+  runtimeType: string;
+  originalRuntimeType: string;
+  originalRuntimeName: string;
+
+  constructor(private dialog: MatDialog,
+              private dialogService: DialogService) {
 
   }
 
@@ -64,12 +79,28 @@
     this.isNested = this.isEventPropertyNested(this.node.data);
     this.timestampProperty = this.isTimestampProperty(this.node.data);
 
+    if (this.node.data instanceof EventProperty) {
+      this.originalRuntimeName = this.findOriginalProperty().runtimeName;
+      this.showFieldStatus = this.fieldStatusInfo && this.fieldStatusInfo[this.originalRuntimeName] !== undefined;
+      this.showEventPreview = this.eventPreview && this.eventPreview.length > 0 && this.eventPreview[0][this.originalRuntimeName] !== undefined;
+      if (this.isPrimitive) {
+        this.originalRuntimeType = this.parseType(this.findOriginalProperty().runtimeType);
+        this.runtimeType = this.parseType((this.node.data as EventPropertyPrimitive).runtimeType);
+      }
+    }
+
     if (!this.node.data.propertyScope) {
       this.node.data.propertyScope = 'MEASUREMENT_PROPERTY';
     }
   }
 
-  ngOnChanges(changes: SimpleChanges): void {
+  private findOriginalProperty(): any {
+    return this.originalEventSchema.eventProperties
+      .find(ep => ep.elementId === this.node.data.elementId);
+  }
+
+  private parseType(runtimeType: string) {
+    return runtimeType.split('#')[1].toUpperCase();
   }
 
   private isEventPropertyPrimitive(instance: EventProperty): boolean {
@@ -109,15 +140,19 @@
   }
 
   public openEditDialog(data): void {
-    const dialogRef = this.dialog.open(EditEventPropertyComponent, {
+    const dialogRef = this.dialogService.open(EditEventPropertyComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Edit field ' + data.runtimeName,
+      width: '50vw',
       data: {
-        property: data,
-        isEditable: this.isEditable
+        'property': data,
+        'isEditable': this.isEditable
       }
     });
-    dialogRef.afterClosed().subscribe(result => {
+
+    dialogRef.afterClosed().subscribe(refresh => {
       this.timestampProperty = this.isTimestampProperty(this.node.data);
-      this.refreshTreeEmitter.emit();
+      this.refreshTreeEmitter.emit(true);
     });
   }
 
@@ -169,7 +204,7 @@
       }
     }
     this.countSelectedChange.emit(this.countSelected);
-    this.refreshTreeEmitter.emit();
+    this.refreshTreeEmitter.emit(false);
   }
 
   public addNestedProperty(eventProperty: EventPropertyNested): void {
@@ -180,6 +215,6 @@
     const property: EventPropertyNested = new EventPropertyNested();
     property.elementId = uuid;
     eventProperty.eventProperties.push(property);
-    this.refreshTreeEmitter.emit();
+    this.refreshTreeEmitter.emit(false);
   }
 }
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.html b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.html
new file mode 100644
index 0000000..d3cad53
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.html
@@ -0,0 +1,41 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="row" fxLayoutGap="15px">
+    <div fxFlex="50" fxLayout="column">
+        <sp-basic-inner-panel [showTitle]="true" panelTitle="Original (Parsed)">
+            <pre [innerHTML]="originalField | jsonpretty" class="preview-text"></pre>
+        </sp-basic-inner-panel>
+    </div>
+
+    <div fxFlex="50" fxLayout="column">
+        <sp-basic-inner-panel [showTitle]="true" panelTitle="Result" fxFlex="100">
+            <div header fxLayoutAlign="end center" fxFlex="100">
+                <button color="accent"
+                        mat-button
+                        data-cy="connect-schema-update-preview-btn"
+                        matTooltip="Update event preview"
+                        (click)="updateEventPreview()">
+                    <mat-icon>refresh</mat-icon>
+                    <span>&nbsp;Update result preview</span>
+                </button>
+            </div>
+            <pre [innerHTML]="desiredField | jsonpretty" class="preview-text"></pre>
+        </sp-basic-inner-panel>
+    </div>
+</div>
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.scss
similarity index 78%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.scss
index a375af7..eddad5e 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.scss
@@ -16,7 +16,14 @@
  *
  */
 
-.md-padding {
+.preview-text {
+  background-color: black;
+  font: 9pt Inconsolata, monospace;
+  text-shadow: 0 0 5px #C8C8C8;
+  color: white;
   padding: 10px;
+  max-width: 100%;
+  max-height: 300px;
+  overflow-y: scroll;
+  white-space: pre-wrap;
 }
-
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.ts b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.ts
new file mode 100644
index 0000000..d7dc13c
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component.ts
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { EventSchema, GuessTypeInfo } from '@streampipes/platform-services';
+
+@Component({
+  selector: 'sp-event-schema-preview',
+  templateUrl: './event-schema-preview.component.html',
+  styleUrls: ['./event-schema-preview.component.scss']
+})
+export class EventSchemaPreviewComponent implements OnInit {
+
+  @Input() originalEventSchema: EventSchema;
+  @Input() desiredEventSchema: EventSchema;
+
+  @Input() originalPreview: Record<string, GuessTypeInfo>;
+  @Input() desiredPreview: Record<string, GuessTypeInfo>;
+
+  @Output() updatePreviewEmitter = new EventEmitter();
+
+  originalField: Record<string, any>;
+  desiredField: Record<string, any>;
+
+  ngOnInit(): void {
+    this.originalField = this.toSimpleMap(this.originalPreview);
+    this.desiredField = this.toSimpleMap(this.desiredPreview);
+  }
+
+  toSimpleMap(event: Record<string, GuessTypeInfo>): Record<string, any> {
+    let result: Record<string, any> = {};
+
+    for (const key in event) {
+      result[key] = event[key].value;
+    }
+
+   result = Object.keys(result).sort().reduce(
+      (obj, key) => {
+        obj[key] = result[key];
+        return obj;
+      },
+      {}
+    );
+
+    return result;
+  }
+
+  public updateEventPreview() {
+    this.updatePreviewEmitter.emit();
+  }
+}
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.html b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.html
new file mode 100644
index 0000000..5990ea8
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.html
@@ -0,0 +1,129 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+
+<div fxLayout="column" fxLayoutAlign="center" class="mt-20">
+    <div fxFlex="90" fxLayout="column">
+        <div fxLayout="column"
+             fxFlex="100"
+             fxLayoutAlign="start center"
+             *ngIf="!isLoading && !isError && schemaErrorHints.length === 0"
+             class="schema-validation schema-validation-ok">
+            <div fxFlex="100"
+                 fxLayout="row"
+                 fxLayoutAlign="start center"
+                 class="schema-validation-text-ok">
+                <i class="material-icons">check_circle</i>&nbsp;<b>Schema ok</b>
+            </div>
+        </div>
+
+        <div fxLayout="column" fxFlex="100" *ngIf="!isLoading && !isError && schemaErrorHints.length > 0">
+            <div fxFlex="100"
+                 fxLayout="column"
+                 [ngClass]="schemaErrorHint.level === 'error' ? 'schema-validation schema-validation-error' : 'schema-validation schema-validation-warning'"
+                 fxLayoutAlign="start center" *ngFor="let schemaErrorHint of schemaErrorHints">
+                <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start"
+                     [ngClass]="schemaErrorHint.level === 'error' ? 'schema-validation-text-error' : 'schema-validation-text-warning'">
+                    <i class="material-icons">warning</i>&nbsp;
+                    <b>{{schemaErrorHint.title}}</b>
+                </div>
+                <div>
+                    <span>{{schemaErrorHint.content}}</span>
+                </div>
+            </div>
+        </div>
+        <sp-basic-inner-panel [showTitle]="false" outerMargin="0px 0px 20px 0px">
+            <div header *ngIf="!isLoading && !isError" fxFlex="100">
+                <sp-schema-editor-header fxFlex="100"
+                                         [countSelected]="countSelected"
+                                         (addNestedPropertyEmitter)="addNestedProperty()"
+                                         (addStaticValuePropertyEmitter)="addStaticValueProperty()"
+                                         (addTimestampPropertyEmitter)="addTimestampProperty()"
+                                         (guessSchemaEmitter)="guessSchema()"
+                                         (updatePreviewEmitter)="updatePreview()"
+                                         (removeSelectedPropertiesEmitter)="removeSelectedProperties()">
+                </sp-schema-editor-header>
+            </div>
+            <div header *ngIf="!isLoading && isError" fxFlex="100">
+                <div fxLayout="row" fxLayoutAlign="end center">
+                    <button color="accent"
+                            mat-button
+                            mat-icon-button
+                            matTooltip="Refresh Schema"
+                            (click)="guessSchema()">
+                        <mat-icon>refresh</mat-icon>
+                    </button>
+                </div>
+            </div>
+
+            <div fxFlex="100">
+
+                <sp-loading-message *ngIf="isLoading"></sp-loading-message>
+
+                <sp-error-message
+                        [errorMessage]="errorMessage"
+                        *ngIf="isError && !isLoading">
+                </sp-error-message>
+
+                <div *ngIf="!isError && !isLoading && eventSchema && oldEventSchema && nodes"
+                     fxLayout="column"
+                     fxLayoutAlign="space-evenly stretched"
+                     class="drag-drop-tree"
+                     data-cy="sp-connect-schema-editor">
+                    <tree-root #tree
+                               [nodes]="nodes"
+                               [options]="options"
+                               (updateData)="onUpdateData(tree)">
+                        <ng-template #treeNodeTemplate let-node let-index="index">
+                            <event-property-row
+                                    [node]="node"
+                                    [(isEditable)]="isEditable"
+                                    [(eventSchema)]="eventSchema"
+                                    [(originalEventSchema)]="oldEventSchema"
+                                    [eventPreview]="eventPreview"
+                                    [fieldStatusInfo]="fieldStatusInfo"
+                                    (refreshTreeEmitter)="refreshTree($event)"
+                                    [(countSelected)]="countSelected"></event-property-row>
+                        </ng-template>
+                    </tree-root>
+                </div>
+            </div>
+        </sp-basic-inner-panel>
+    </div>
+    <div fxFlex="100" *ngIf="desiredPreview && isPreviewEnabled && !isLoading && !isError">
+        <sp-event-schema-preview [originalEventSchema]="oldEventSchema"
+                                 [desiredEventSchema]="eventSchema"
+                                 [originalPreview]="eventPreview[0]"
+                                 [desiredPreview]="desiredPreview"
+                                 (updatePreviewEmitter)="updatePreview()"></sp-event-schema-preview>
+    </div>
+</div>
+
+
+<div fxLayoutAlign="end" class="mt-10">
+    <button class="mat-basic" mat-raised-button (click)="removeSelection()">Cancel</button>
+    <button class="mat-basic stepper-button" mat-raised-button (click)="goBack()">Back</button>
+    <button class="stepper-button"
+            id="event-schema-next-button"
+            data-cy="sp-event-schema-next-button"
+            color="accent" mat-raised-button
+            (click)="clickNext()"
+            [disabled]="!validEventSchema">
+        Next
+    </button>
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.scss b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.scss
similarity index 87%
rename from ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.scss
rename to ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.scss
index ff253bb..228a3ae 100644
--- a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.scss
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.scss
@@ -171,3 +171,39 @@
 .add-schema button:disabled {
   color: rgba(0, 0, 0, 0.26);
 }
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.schema-validation {
+  margin-bottom: 10px;
+  border: 2px solid var(--color-bg-3);
+  padding: 10px;
+  min-height: 50px;
+  text-align: center;
+}
+
+.schema-validation-ok {
+  border: 2px solid #629f62;
+}
+
+.schema-validation-error {
+  border: 2px solid #963e3e;
+}
+
+.schema-validation-warning {
+  border: 2px solid #d09836;
+}
+
+.schema-validation-text-ok {
+  color: #629f62;
+}
+
+.schema-validation-text-error {
+  color: #963e3e;
+}
+
+.schema-validation-text-warning {
+  color: #d09836;
+}
diff --git a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.ts b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.ts
similarity index 73%
rename from ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.ts
rename to ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.ts
index 8cf453f..30c340a 100644
--- a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.ts
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.ts
@@ -17,10 +17,10 @@
  */
 
 import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core';
-import { RestService } from '../../../services/rest.service';
+import { RestService } from '../../../../services/rest.service';
 import { ITreeOptions, TreeComponent } from '@circlon/angular-tree-component';
 import { UUID } from 'angular2-uuid';
-import { DataTypesService } from '../../../services/data-type.service';
+import { DataTypesService } from '../../../../services/data-type.service';
 import {
   AdapterDescription,
   EventProperty,
@@ -31,7 +31,12 @@
   Notification
 } from '@streampipes/platform-services';
 import { MatStepper } from '@angular/material/stepper';
-import { UserErrorMessage } from '../../../../core-model/base/UserErrorMessage';
+import { UserErrorMessage } from '../../../../../core-model/base/UserErrorMessage';
+import {
+  FieldStatusInfo, GuessTypeInfo,
+  StreamPipesErrorMessage
+} from '../../../../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+import { TransformationRuleService } from '../../../../services/transformation-rule.service';
 
 @Component({
   selector: 'sp-event-schema',
@@ -40,7 +45,9 @@
 })
 export class EventSchemaComponent implements OnChanges {
 
-  constructor(private restService: RestService, private dataTypesService: DataTypesService) {
+  constructor(private restService: RestService,
+              private dataTypesService: DataTypesService,
+              private transformationRuleService: TransformationRuleService ) {
   }
 
   @Input() adapterDescription: AdapterDescription;
@@ -73,11 +80,15 @@
   isLoading = false;
   isError = false;
   isPreviewEnabled = false;
-  errorMessages: Notification[];
+  errorMessage: StreamPipesErrorMessage;
   nodes: EventProperty[] = new Array<EventProperty>();
   validEventSchema = false;
   schemaErrorHints: UserErrorMessage[] = [];
 
+  eventPreview: Record<string, GuessTypeInfo>[];
+  desiredPreview: Record<string, GuessTypeInfo>;
+  fieldStatusInfo: Record<string, FieldStatusInfo>;
+
   options: ITreeOptions = {
     childrenField: 'eventProperties',
     allowDrag: () => {
@@ -98,6 +109,8 @@
     this.isLoading = true;
     this.isError = false;
     this.restService.getGuessSchema(this.adapterDescription).subscribe(guessSchema => {
+        this.eventPreview = guessSchema.eventPreview;
+        this.fieldStatusInfo = guessSchema.fieldStatusInfo;
         this.eventSchema = guessSchema.eventSchema;
         this.eventSchema.eventProperties.sort((a, b) => {
           return a.runtimeName < b.runtimeName ? -1 : 1;
@@ -115,9 +128,13 @@
         this.isEditable = true;
         this.isEditableChange.emit(true);
         this.isLoading = false;
+
+        if (guessSchema.eventPreview && guessSchema.eventPreview.length > 0) {
+          this.updatePreview();
+        }
       },
       errorMessage => {
-        this.errorMessages = errorMessage.error.notifications;
+        this.errorMessage = errorMessage.error;
         this.isError = true;
         this.isLoading = false;
         this.eventSchema = new EventSchema();
@@ -125,11 +142,13 @@
 
   }
 
-  private refreshTree(): void {
+  private refreshTree(refreshPreview = true): void {
     this.nodes = new Array<EventProperty>();
     this.nodes.push(this.eventSchema as unknown as EventProperty);
     this.validEventSchema = this.checkIfValid(this.eventSchema);
-    // this.tree.treeModel.update();
+    if (refreshPreview) {
+      this.updatePreview();
+    }
   }
 
   public addNestedProperty(eventProperty?: EventPropertyNested): void {
@@ -192,8 +211,20 @@
     this.refreshTree();
   }
 
-  public togglePreview(): void {
-    this.isPreviewEnabled = !this.isPreviewEnabled;
+  public updatePreview(): void {
+    this.isPreviewEnabled = false;
+    this.transformationRuleService.setOldEventSchema(this.oldEventSchema);
+    this.transformationRuleService.setNewEventSchema(this.eventSchema);
+    const ruleDescriptions = this.transformationRuleService.getTransformationRuleDescriptions();
+    if (this.eventPreview && this.eventPreview.length > 0) {
+      this.restService.getAdapterEventPreview({
+        rules: ruleDescriptions,
+        inputData: this.eventPreview[0]
+      }).subscribe(preview => {
+        this.desiredPreview = preview;
+        this.isPreviewEnabled = true;
+      });
+    }
   }
 
   ngOnChanges(changes: SimpleChanges) {
@@ -226,7 +257,20 @@
 
     this.schemaErrorHints = [];
     if (!hasTimestamp) {
-      this.schemaErrorHints.push(new UserErrorMessage('Missing Timestamp', 'The timestamp must be a UNIX timestamp in milliseconds. Edit the timestamp event property or add a timestamp with the button on the top left.'));
+      this.schemaErrorHints.push(new UserErrorMessage('Missing Timestamp', 'The timestamp must be a UNIX timestamp in milliseconds. Edit the timestamp field or add an ingestion timestamp.'));
+    }
+
+    if (this.fieldStatusInfo) {
+      const badFields = eventSchema.eventProperties
+        .filter(ep => this.fieldStatusInfo[ep.runtimeName] !== undefined)
+        .map(ep => this.fieldStatusInfo[ep.runtimeName])
+        .find(field => field.fieldStatus !== 'GOOD');
+      if (badFields !== undefined) {
+        this.schemaErrorHints.push(new UserErrorMessage(
+          'Bad reading',
+          'At least one field could not be properly read. If this is a permanent problem, consider removing it - keeping this field might cause the adapter to fail or to omit sending events.',
+          'warning'));
+      }
     }
 
     return hasTimestamp;
diff --git a/ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html b/ui/src/app/connect/components/new-adapter/schema-editor/loading-message/loading-message.component.html
similarity index 90%
rename from ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html
rename to ui/src/app/connect/components/new-adapter/schema-editor/loading-message/loading-message.component.html
index 639fd6c..4ef8106 100644
--- a/ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/loading-message/loading-message.component.html
@@ -18,9 +18,9 @@
 
 <div fxLayout="column" >
     <div fxLayoutAlign="center">
-        <mat-spinner fxLayoutAlign="center" style="margin: 10px 0 5px 0" color="accent">Loading</mat-spinner>
+        <mat-spinner fxLayoutAlign="center" style="margin: 10px 0 5px 0" color="accent" [diameter]="30">Loading</mat-spinner>
     </div>
     <div fxLayoutAlign="center">
-        <h3>Guessing the event schema...</h3>
+        <h4>Guessing the event schema...</h4>
     </div>
 </div>
diff --git a/ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.scss b/ui/src/app/connect/components/new-adapter/schema-editor/loading-message/loading-message.component.scss
similarity index 100%
rename from ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.scss
rename to ui/src/app/connect/components/new-adapter/schema-editor/loading-message/loading-message.component.scss
diff --git a/ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.ts b/ui/src/app/connect/components/new-adapter/schema-editor/loading-message/loading-message.component.ts
similarity index 100%
rename from ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.ts
rename to ui/src/app/connect/components/new-adapter/schema-editor/loading-message/loading-message.component.ts
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.html b/ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.html
new file mode 100644
index 0000000..8418201
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.html
@@ -0,0 +1,66 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="row" fxFlex="100">
+    <div fxFlex fxLayoutAlign="start center" fxLayout="row">
+        <button color="accent"
+                mat-button
+                data-cy="connect-add-nested-property"
+                matTooltip="Add a Nested Property"
+                (click)=addNestedProperty()>
+            <mat-icon>queue</mat-icon>
+            <span>&nbsp;Add nested</span>
+        </button>
+        <button color="accent"
+                mat-button
+                data-cy="connect-add-static-property"
+                matTooltip="Add a static value to event"
+                (click)="addStaticValueProperty()">
+            <mat-icon>add</mat-icon>
+            <span>&nbsp;Add static value</span>
+        </button>
+        <button color="accent"
+                mat-button
+                data-cy="connect-schema-add-timestamp-btn"
+                matTooltip="Add timestamp to event schema"
+                (click)="addTimestampProperty()">
+            <mat-icon>access_time</mat-icon>
+            <span>&nbsp;Add timestamp</span>
+        </button>
+    </div>
+    <div fxLayout="row" fxLayoutAlign="end center">
+        <button color="accent"
+                mat-button
+                mat-icon-button
+                matTooltip="Refresh Schema"
+                (click)="guessSchema()">
+            <mat-icon>refresh</mat-icon>
+        </button>
+
+        <button style="padding-right:0"
+                color="accent"
+                mat-button
+                mat-icon-button
+                matTooltip="Remove selected Properties"
+                [disabled]="countSelected == 0"
+                (click)="removeSelectedProperties()"
+                data-cy="connect-schema-delete-properties-btn">
+            <mat-icon>delete</mat-icon>
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.scss
similarity index 99%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.scss
index 58ba04b..13cbc4a 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.scss
@@ -15,4 +15,3 @@
  * limitations under the License.
  *
  */
-
diff --git a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.ts b/ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.ts
similarity index 86%
rename from ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.ts
rename to ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.ts
index 1b757ba..7bcd8cc 100644
--- a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.ts
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component.ts
@@ -17,7 +17,7 @@
  */
 
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { UserErrorMessage } from '../../../../core-model/base/UserErrorMessage';
+import { UserErrorMessage } from '../../../../../core-model/base/UserErrorMessage';
 
 @Component({
   selector: 'sp-schema-editor-header',
@@ -28,14 +28,12 @@
 
 
   @Input() countSelected: number;
-  @Input() schemaErrorHints: UserErrorMessage[];
-  @Input() displayMessages: boolean;
 
   @Output() addNestedPropertyEmitter = new EventEmitter();
   @Output() addStaticValuePropertyEmitter = new EventEmitter();
   @Output() addTimestampPropertyEmitter = new EventEmitter();
   @Output() guessSchemaEmitter = new EventEmitter();
-  @Output() togglePreviewEmitter = new EventEmitter();
+  @Output() updatePreviewEmitter = new EventEmitter();
   @Output() removeSelectedPropertiesEmitter = new EventEmitter();
 
   constructor() { }
@@ -59,10 +57,6 @@
     this.guessSchemaEmitter.emit();
   }
 
-  public togglePreview() {
-    this.togglePreviewEmitter.emit();
-  }
-
   public removeSelectedProperties() {
     this.removeSelectedPropertiesEmitter.emit();
   }
diff --git a/ui/src/app/connect/components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component.html b/ui/src/app/connect/components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component.html
new file mode 100644
index 0000000..5754e1c
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component.html
@@ -0,0 +1,58 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column">
+    <div fxFlex="100" fxLayout="column">
+        <sp-basic-inner-panel panelTitle="Basic Settings" outerMargin="20px 0px">
+            <div header fxFlex="100" fxLayout="row" fxLayoutAlign="end center" class="pr-5">
+                <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center" *ngIf="availableTemplates && availableTemplates.length > 0">
+                    <mat-form-field class="form-field" floatLabel="never" color="accent">
+                        <mat-label>Use template</mat-label>
+                        <mat-select (selectionChange)="loadTemplate($event)"
+                                    [(value)]="selectedTemplate">
+                            <mat-option>--</mat-option>
+                            <mat-option [value]="template" *ngFor="let template of availableTemplates">
+                                {{template.templateName}}
+                            </mat-option>
+                        </mat-select>
+                    </mat-form-field>
+                </div>
+            </div>
+            <sp-configuration-group
+                    [configurationGroup]="specificAdapterForm"
+                    [adapterId]="adapterDescription.appId"
+                    [configuration]="adapterDescription.config">
+            </sp-configuration-group>
+        </sp-basic-inner-panel>
+    </div>
+
+    <div fxLayoutAlign="end">
+        <button class="mat-basic"
+                mat-raised-button
+                style="margin-right: 10px;"
+                (click)="removeSelection()">Cancel</button>
+        <button mat-button mat-raised-button
+                class="mat-basic"
+                (click)="openTemplateDialog()">Store config as template</button>
+        <div id="specific-settings-next-button">
+            <button class="stepper-button" [disabled]="!specificAdapterSettingsFormValid"
+                    (click)="clickNext()" color="accent" mat-raised-button>Next
+            </button>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/specific-adapter-configuration/specific-adapter-configuration.component.scss b/ui/src/app/connect/components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component.scss
similarity index 100%
rename from ui/src/app/connect/components/specific-adapter-configuration/specific-adapter-configuration.component.scss
rename to ui/src/app/connect/components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component.scss
diff --git a/ui/src/app/connect/components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component.ts b/ui/src/app/connect/components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component.ts
new file mode 100644
index 0000000..2ef6de8
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component.ts
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { AdapterDescription, PipelineElementTemplateService } from '@streampipes/platform-services';
+import { FormBuilder, FormGroup } from '@angular/forms';
+import { DialogService } from '@streampipes/shared-ui';
+import { AdapterTemplateService } from '../../../services/adapter-template.service';
+import { AdapterConfigurationDirective } from '../adapter-configuration.directive';
+
+@Component({
+  selector: 'sp-specific-adapter-configuration',
+  templateUrl: './specific-adapter-configuration.component.html',
+  styleUrls: ['./specific-adapter-configuration.component.scss']
+})
+export class SpecificAdapterConfigurationComponent extends AdapterConfigurationDirective implements OnInit {
+
+  specificAdapterSettingsFormValid: boolean;
+
+  specificAdapterForm: FormGroup;
+
+
+  constructor(_formBuilder: FormBuilder,
+              dialogService: DialogService,
+              pipelineElementTemplateService: PipelineElementTemplateService,
+              adapterTemplateService: AdapterTemplateService) {
+    super(_formBuilder, dialogService, pipelineElementTemplateService, adapterTemplateService);
+  }
+
+  ngOnInit(): void {
+    super.onInit();
+    this.cachedAdapterDescription = {...this.adapterDescription};
+    // initialize form for validation
+    this.specificAdapterForm = this._formBuilder.group({});
+    this.specificAdapterForm.statusChanges.subscribe((status) => {
+      this.specificAdapterSettingsFormValid = this.specificAdapterForm.valid;
+    });
+
+    // Go directly to event schema configuration when adapter has no configuration properties
+    if (this.adapterDescription.config.length === 0) {
+      this.specificAdapterSettingsFormValid = true;
+    }
+  }
+
+  openTemplateDialog(): void {
+    const dialogRef = this.adapterTemplateService.getDialog(this.adapterDescription.config, this.adapterDescription.appId);
+
+    dialogRef.afterClosed().subscribe(refresh => {
+      this.loadPipelineElementTemplates();
+    });
+  }
+
+  afterTemplateReceived(adapterDescription: any) {
+    this.adapterDescription = AdapterDescription.fromDataUnion(adapterDescription);
+    this.updateAdapterDescriptionEmitter.emit(this.adapterDescription);
+  }
+
+}
+
diff --git a/ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.html b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.html
new file mode 100644
index 0000000..4a769b4
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.html
@@ -0,0 +1,41 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column" class="options-panel">
+    <div fxLayout="row" fxFlex="100" fxLayoutAlign="start start">
+        <div class="mr-15" fxLayoutAlign="start start">
+            <mat-icon class="icon">{{optionIcon}}</mat-icon>
+        </div>
+        <div fxFlex fxLayout="column">
+            <div fxFlex="100" class="title" fxLayout="row">
+                <div fxLayoutAlign="start start" class="mr-15">
+                    <mat-checkbox (change)="optionSelectedEmitter.emit($event.checked)"
+                                  [attr.data-cy]="dataCy" class="large-checkbox">
+                    </mat-checkbox>
+                </div>
+                <div fxFlex fxLayout="column">
+                    <div>{{optionTitle}}</div>
+                    <mat-hint class="description">{{optionDescription}}</mat-hint>
+                </div>
+            </div>
+
+            <ng-content></ng-content>
+        </div>
+    </div>
+
+</div>
diff --git a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.scss
similarity index 62%
copy from ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss
copy to ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.scss
index 2c1a70e..60e5397 100644
--- a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss
+++ b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.scss
@@ -16,19 +16,30 @@
  *
  */
 
-@import '../../../../scss/sp/sp-dialog.scss';
+.options-panel {
+  border-left: 4px solid var(--color-accent);
+  border-bottom: 1px solid var(--color-bg-2);
+  border-top: 1px solid var(--color-bg-2);
+  border-right: 1px solid var(--color-bg-2);
+  padding: 8px;
+  background: var(--color-bg-1);
+  margin-top: 6px;
+  margin-bottom: 6px;
+}
 
-.divider {
-  margin-top: 10px;
+.title {
+  color: var(--color-default-text);
+  font-weight: 600;
+  font-size: 13pt;
   margin-bottom: 10px;
 }
 
-.static-property-panel {
-  padding-left: 10px;
-  margin-bottom: 10px;
-  margin-top: 10px;
+.description {
+  font-size: 10pt;
 }
 
-.static-property-panel-border {
-  border-left:5px solid gray;
+.icon {
+  margin-right: 10px;
+  color: var(--color-accent);
+  font-size: 22pt;
 }
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.ts
similarity index 61%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
copy to ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.ts
index 4e64c25..399ff42 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
+++ b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.ts
@@ -16,23 +16,30 @@
  *
  */
 
-import { Component, Input, OnInit } from '@angular/core';
-import { Notification } from '@streampipes/platform-services';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 
 @Component({
-  selector: 'sp-error-message',
-  templateUrl: './error-message.component.html',
-  styleUrls: ['./error-message.component.scss']
+  selector: 'sp-adapter-options-panel',
+  templateUrl: './adapter-options-panel.component.html',
+  styleUrls: ['./adapter-options-panel.component.scss']
 })
-export class ErrorMessageComponent implements OnInit {
+export class SpAdapterOptionsPanelComponent {
 
-  @Input() errorMessages: Notification[];
+  @Input()
+  optionTitle: string;
 
-  showErrorMessage = false;
+  @Input()
+  optionDescription: string;
 
-  constructor() { }
+  @Input()
+  optionIcon: string;
 
-  ngOnInit(): void {
-  }
+  @Input()
+  dataCy: string;
+
+  @Output()
+  optionSelectedEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
 
 }
+
+
diff --git a/ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.html b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.html
new file mode 100644
index 0000000..46da68a
--- /dev/null
+++ b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.html
@@ -0,0 +1,104 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div [formGroup]="startAdapterForm" fxLayout="column" fxFlex="100">
+    <sp-basic-inner-panel panelTitle="Adapter settings" outerMargin="20px 0px 10px 0px">
+        <div fxFlex="100">
+            <div fxLayoutAlign="center" fxLayout="column" fxFlex="100">
+                <mat-form-field color="accent">
+                    <input formControlName="adapterName"
+                           matInput id="input-AdapterName" placeholder="Adapter Name"
+                           data-cy="sp-adapter-name" required>
+                </mat-form-field>
+                <mat-form-field color="accent">
+                    <input matInput id="input-AdapterDescription" [ngModelOptions]="{standalone: true}"
+                           placeholder="Adapter Description" [(ngModel)]="adapterDescription.description">
+                </mat-form-field>
+            </div>
+        </div>
+    </sp-basic-inner-panel>
+
+    <div fxFlex="100" fxLayout="column">
+        <sp-adapter-options-panel optionTitle="Remove Duplicates"
+                                  optionDescription="Avoid duplicated events within a certain time interval"
+                                  optionIcon="cleaning_services"
+                                  dataCy="connect-remove-duplicates-box"
+                                  (optionSelectedEmitter)="removeDuplicates = $event">
+            <mat-form-field *ngIf="removeDuplicates" color="accent">
+                <input matInput id="input-removeDuplicatesTime"
+                       [ngModelOptions]="{standalone: true}" placeholder="Remove Duplicates Time Window"
+                       [(ngModel)]="removeDuplicatesTime"
+                       data-cy="connect-remove-duplicates-input">
+            </mat-form-field>
+        </sp-adapter-options-panel>
+
+
+        <sp-adapter-options-panel optionTitle="Reduce event rate"
+                                  optionDescription="Send maximum one event in the specified time window"
+                                  optionIcon="speed"
+                                  dataCy="connect-reduce-event-rate-box"
+                                  (optionSelectedEmitter)="eventRateReduction = $event">
+            <mat-form-field *ngIf="eventRateReduction" color="accent">
+                <input type="number" matInput id="input-evenRateTime"
+                       [ngModelOptions]="{standalone: true}" [(ngModel)]="eventRateTime"
+                       placeholder="Time Window (Milliseconds)" matTooltipPosition="above"
+                       data-cy="connect-reduce-event-input">
+            </mat-form-field>
+            <mat-form-field *ngIf="eventRateReduction" color="accent">
+                <mat-label>Event Aggregation</mat-label>
+                <mat-select [(ngModel)]="eventRateMode" [ngModelOptions]="{standalone: true}">
+                    <mat-option class="md-elevation-z1" style="background: white;"
+                                matTooltip="Last Event in Time Window" value="none">
+                        None
+                    </mat-option>
+                </mat-select>
+            </mat-form-field>
+        </sp-adapter-options-panel>
+
+        <!-- Start pipeline template to store raw events in data lake -->
+        <sp-adapter-options-panel optionTitle="Persist events"
+                                  optionDescription="Store all events of this source in the internal data store"
+                                  optionIcon="save"
+                                  dataCy="sp-store-in-datalake"
+                                  (optionSelectedEmitter)="handlePersistOption($event)">
+            <mat-form-field *ngIf="saveInDataLake" color="accent">
+                <mat-label>Select Time Field</mat-label>
+                <mat-select [(ngModel)]="dataLakeTimestampField"
+                            [ngModelOptions]="{standalone: true}"
+                            data-cy="sp-store-in-datalake-timestamp">
+                    <mat-option class="md-elevation-z1" style="background: white;"
+                                *ngFor="let timestampField of eventSchema.eventProperties | timestampFilter"
+                                [value]="timestampField.runtimeName">
+                        {{timestampField.runtimeName}}
+                    </mat-option>
+                </mat-select>
+            </mat-form-field>
+        </sp-adapter-options-panel>
+    </div>
+
+    <div fxLayoutAlign="end" style="margin-top: 10px;">
+        <button class="mat-basic" mat-raised-button (click)="removeSelection()">Cancel</button>
+        <button style="margin-left:10px;" class="mat-basic stepper-button" mat-raised-button (click)="goBack()">Back
+        </button>
+        <button [disabled]="!(startAdapterSettingsFormValid)" mat-raised-button id="button-startAdapter"
+                color="accent" (click)="startAdapter()" mat-button style="margin-left:10px;">
+            Start Adapter
+        </button>
+    </div>
+</div>
+
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.scss
similarity index 99%
rename from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
rename to ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.scss
index 58ba04b..c2ade4c 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.scss
@@ -16,3 +16,4 @@
  *
  */
 
+
diff --git a/ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.ts b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.ts
similarity index 88%
rename from ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.ts
rename to ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.ts
index 5c59ac0..a498ca4 100644
--- a/ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.ts
+++ b/ui/src/app/connect/components/new-adapter/start-adapter-configuration/start-adapter-configuration.component.ts
@@ -22,18 +22,14 @@
   EventProperty,
   EventRateTransformationRuleDescription,
   EventSchema,
-  GenericAdapterSetDescription,
   RemoveDuplicatesTransformationRuleDescription,
-  SpecificAdapterSetDescription
 } from '@streampipes/platform-services';
 import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
 import { MatStepper } from '@angular/material/stepper';
-import { AdapterStartedDialog } from '../../dialog/adapter-started/adapter-started-dialog.component';
+import { AdapterStartedDialog } from '../../../dialog/adapter-started/adapter-started-dialog.component';
 import { PanelType, DialogService } from '@streampipes/shared-ui';
-import { ShepherdService } from '../../../services/tour/shepherd.service';
-import { ConnectService } from '../../services/connect.service';
-import { TimestampPipe } from '../../filter/timestamp.pipe';
-import { MatCheckboxChange } from '@angular/material/checkbox';
+import { ShepherdService } from '../../../../services/tour/shepherd.service';
+import { TimestampPipe } from '../../../filter/timestamp.pipe';
 
 @Component({
   selector: 'sp-start-adapter-configuration',
@@ -90,7 +86,6 @@
   constructor(
     private dialogService: DialogService,
     private shepherdService: ShepherdService,
-    private connectService: ConnectService,
     private _formBuilder: FormBuilder,
     private timestampPipe: TimestampPipe) {
   }
@@ -100,13 +95,13 @@
     this.startAdapterForm = this._formBuilder.group({});
     this.startAdapterForm.addControl('adapterName', new FormControl(this.adapterDescription.name, Validators.required));
     this.startAdapterForm.valueChanges.subscribe(v => this.adapterDescription.name = v.adapterName);
-    this.startAdapterForm.statusChanges.subscribe((status) => {
+    this.startAdapterForm.statusChanges.subscribe(() => {
       this.startAdapterSettingsFormValid = this.startAdapterForm.valid;
     });
   }
 
-  findDefaultTimestamp(event: MatCheckboxChange) {
-    if (event.checked) {
+  findDefaultTimestamp(selected: boolean) {
+    if (selected) {
       const timestampFields = this.timestampPipe.transform(this.eventSchema.eventProperties);
       if (timestampFields.length > 0) {
         this.dataLakeTimestampField = timestampFields[0].runtimeName;
@@ -144,7 +139,7 @@
 
     this.shepherdService.trigger('button-startAdapter');
 
-    dialogRef.afterClosed().subscribe(result => {
+    dialogRef.afterClosed().subscribe(() => {
       this.adapterStartedEmitter.emit();
     });
   }
@@ -161,4 +156,8 @@
     this.goBackEmitter.emit();
   }
 
+  handlePersistOption(selected: boolean) {
+    this.saveInDataLake = selected;
+    this.findDefaultTimestamp(selected);
+  }
 }
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.html b/ui/src/app/connect/components/schema-editor/error-message/error-message.component.html
deleted file mode 100644
index 3c7e8b0..0000000
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div fxLayout="column" >
-    <div fxLayout="row" fxLayoutAlign="center center">
-        <mat-icon style="margin-top: 10px" class="md-accent">warning</mat-icon>
-        <span style="width: 10px;"></span>
-        <h3>Sorry, there was an error while guessing the schema of your configured data source...</h3>
-    </div>
-    <div fxLayout="row" fxLayoutAlign="center center">
-        <button mat-button class="md-accent">
-            <div *ngIf="!showErrorMessage" (click)="showErrorMessage = true">Show Details</div>
-            <div *ngIf="showErrorMessage" (click)="showErrorMessage = false">Hide Details</div>
-        </button>
-    </div>
-    <div fxLayoutAlign="center center" *ngIf="showErrorMessage">
-        <div class="error-message">
-            <div *ngFor="let error of errorMessages" style="margin-bottom: 5px; margin-top: 5px">
-                <div>{{error.title}}</div>
-                <div>{{error.description}}</div>
-            </div>
-        </div>
-    </div>
-</div>
diff --git a/ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.html b/ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.html
deleted file mode 100644
index df17659..0000000
--- a/ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div fxLayout="row">
-    <div fxFlex="1 1 auto" fxLayout="row">
-        <b>
-            {{ label }}
-        </b>
-        <mat-icon *ngIf="timestampProperty"
-                  style="font-size: 15px; padding: 4px;">
-            access_time
-        </mat-icon>
-        <p style="margin: 0px 10px 10px;" *ngIf="isList">[List]</p>
-    </div>
-
-    <div fxFlex="15" *ngIf="isPrimitive">
-        <mat-select [(ngModel)]="node.data.propertyScope"
-                    [attr.data-cy]="'property-scope-' + label">
-            <mat-option value="MEASUREMENT_PROPERTY">Measurement</mat-option>
-            <mat-option value="DIMENSION_PROPERTY">Dimension</mat-option>
-            <mat-option value="HEADER_PROPERTY">Header</mat-option>
-        </mat-select>
-    </div>
-
-    <div fxFlex="0 1 auto" fxLayoutAlign="center center"
-         *ngIf="isNested">
-        <button [disabled]="!isEditable" color="accent" mat-button (click)=addNestedProperty(node.data)>
-            <mat-icon matTooltip="Add a Nested Property">queue</mat-icon>
-        </button>
-    </div>
-    <div fxFlex="0 1 auto" fxLayoutAlign="center center"
-         *ngIf="isNested || isPrimitive || isList">
-        <button [disabled]="!isEditable" color="accent" mat-button
-                (click)="openEditDialog(node.data)"
-                [attr.data-cy]="'edit-' + label.toLowerCase()">
-            <mat-icon>edit</mat-icon>
-        </button>
-    </div>
-    <div fxFlex="0 1 auto" fxLayoutAlign="center center">
-        <mat-checkbox
-                *ngIf="isNested || isPrimitive || isList"
-                (click)="selectProperty(node.data.id, undefined)"
-                [disabled]="!isEditable"
-                [class.checkbox-selected]="node.data.selected"
-                [checked]="node.data.selected"
-                [attr.data-cy]="'delete-property-' + label.toLowerCase()">
-        </mat-checkbox>
-    </div>
-</div>
diff --git a/ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.scss b/ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.scss
deleted file mode 100644
index a3becc8..0000000
--- a/ui/src/app/connect/components/schema-editor/event-property-row/event-property-row.component.scss
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-
-::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background {
-    background-color: var(--color-accent) !important;
-}
-
-::ng-deep .mat-checkbox:not(.mat-checkbox-disabled).mat-accent .mat-checkbox-ripple .mat-ripple-element {
-    background-color: var(--color-accent) !important;
-}
-
-.checkbox-selected {
-    opacity: 1 !important;
-}
diff --git a/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.scss b/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.scss
deleted file mode 100644
index 58ba04b..0000000
--- a/ui/src/app/connect/components/schema-editor/event-schema-preview/event-schema-preview.component.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
diff --git a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.html b/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.html
deleted file mode 100644
index 54c5fee..0000000
--- a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-
-<div fxLayout="row" fxLayoutAlign="center">
-    <div fxFlex="0 1 80%">
-
-        <div class="assemblyOptions sp-blue-bg" *ngIf="!isLoading && !isError">
-            <sp-schema-editor-header
-                    [countSelected]="countSelected"
-                    [schemaErrorHints]="schemaErrorHints"
-                    [displayMessages]="validEventSchema"
-                    (addNestedPropertyEmitter)="addNestedProperty()"
-                    (addStaticValuePropertyEmitter)="addStaticValueProperty()"
-                    (addTimestampPropertyEmitter)="addTimestampProperty()"
-                    (guessSchemaEmitter)="guessSchema()"
-                    (togglePreviewEmitter)="togglePreview()"
-                    (removeSelectedPropertiesEmitter)="removeSelectedProperties()">
-            </sp-schema-editor-header>
-        </div>
-
-        <div class="sp-blue-border padding">
-
-            <sp-loading-message *ngIf="isLoading"></sp-loading-message>
-
-            <sp-error-message
-                    [errorMessages]="errorMessages"
-                    *ngIf="isError">
-            </sp-error-message>
-
-            <div *ngIf="!isError && !isLoading"
-                 fxLayout="column"
-                 fxLayoutAlign="space-evenly stretched"
-                 class="drag-drop-tree"
-                 data-cy="sp-connect-schema-editor">
-                <tree-root #tree
-                           [nodes]="nodes"
-                           [options]="options"
-                           (updateData)="onUpdateData(tree)">
-                    <ng-template #treeNodeTemplate let-node let-index="index">
-                        <event-property-row
-                                [node]="node"
-                                [(isEditable)]="isEditable"
-                                [(eventSchema)]="eventSchema"
-                                (refreshTreeEmitter)="refreshTree()"
-                                [(countSelected)]="countSelected"></event-property-row>
-                    </ng-template>
-                </tree-root>
-            </div>
-        </div>
-    </div>
-    <div fxFlex="0 1 50%" *ngIf="isPreviewEnabled">
-        <sp-event-schema-preview [eventSchema]="eventSchema"></sp-event-schema-preview>
-    </div>
-</div>
-
-
-<div fxLayoutAlign="end">
-    <button class="mat-basic" mat-raised-button (click)="removeSelection()">Cancel</button>
-    <button class="mat-basic stepper-button" mat-raised-button (click)="goBack()">Back</button>
-    <button class="stepper-button"
-            id="event-schema-next-button"
-            data-cy="sp-event-schema-next-button"
-            color="accent" mat-raised-button
-            (click)="clickNext()"
-            [disabled]="!validEventSchema">
-        Next
-    </button>
-</div>
diff --git a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.html b/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.html
deleted file mode 100644
index 2c30634..0000000
--- a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div fxLayout="row">
-    <div fxLayoutAlign="space-between center" class="add-schema" fxFlex="0 1 100%">
-        <div>
-            <button color="primary"
-                    mat-button
-                    data-cy="connect-add-nested-property"
-                    (click)=addNestedProperty()>
-                <mat-icon matTooltip="Add a Nested Property">queue</mat-icon>
-            </button>
-            <button color="primary"
-                    mat-button
-                    data-cy="connect-add-static-property"
-                    (click)="addStaticValueProperty()">
-                <mat-icon matTooltip="Add a static value to event">add</mat-icon>
-            </button>
-            <button color="primary"
-                    mat-button
-                    data-cy="connect-add-timestamp-property"
-                    (click)=addTimestampProperty()
-                    data-cy="connect-schema-add-timestamp-btn">
-                <mat-icon matTooltip="Add timestamp to event schema">access_time</mat-icon>
-            </button>
-            <button color="primary"
-                    mat-button
-                    (click)=guessSchema()>
-                <mat-icon matTooltip="Refresh Schema">refresh</mat-icon>
-            </button>
-            <!--            <button color="primary" mat-button (click)=togglePreview()>-->
-            <!--                <mat-icon matTooltip="Show preview of schema">play_arrow</mat-icon>-->
-            <!--            </button>-->
-        </div>
-        <div fxLayout="row" style="align-items: center;">
-                <sp-error-hint
-                        [errorMessages]="schemaErrorHints"
-                        [displayMessages]="!displayMessages">
-                </sp-error-hint>
-
-
-            <button style="padding-right:0"
-                    color="primary"
-                    mat-button
-                    [disabled]="countSelected == 0"
-                    (click)="removeSelectedProperties()"
-                    data-cy="connect-schema-delete-properties-btn">
-                <mat-icon matTooltip="Remove selected Properties">delete</mat-icon>
-            </button>
-        </div>
-    </div>
-</div>
diff --git a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.scss b/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.scss
deleted file mode 100644
index 52bd5d6..0000000
--- a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.scss
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-.add-schema button {
-    color: white;
-}
\ No newline at end of file
diff --git a/ui/src/app/connect/components/specific-adapter-configuration/specific-adapter-configuration.component.html b/ui/src/app/connect/components/specific-adapter-configuration/specific-adapter-configuration.component.html
deleted file mode 100644
index e5923e3..0000000
--- a/ui/src/app/connect/components/specific-adapter-configuration/specific-adapter-configuration.component.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div style="margin-bottom: 2%;">
-    <div>
-        <div class="assemblyOptions sp-blue-bg">
-            <h4>Basic settings</h4>
-        </div>
-
-        <sp-configuration-group
-                [configurationGroup]="specificAdapterForm"
-                [adapterId]="adapterDescription.appId"
-                [configuration]="adapterDescription.config">
-        </sp-configuration-group>
-
-    </div>
-</div>
-
-<div fxLayoutAlign="end">
-    <button class="mat-basic" mat-raised-button (click)="removeSelection()">Cancel</button>
-    <div id="specific-settings-next-button">
-        <button class="stepper-button" [disabled]="!specificAdapterSettingsFormValid"
-                (click)="clickNext()" color="accent" mat-raised-button>Next
-        </button>
-    </div>
-</div>
diff --git a/ui/src/app/connect/components/specific-adapter-configuration/specific-adapter-configuration.component.ts b/ui/src/app/connect/components/specific-adapter-configuration/specific-adapter-configuration.component.ts
deleted file mode 100644
index e848ed1..0000000
--- a/ui/src/app/connect/components/specific-adapter-configuration/specific-adapter-configuration.component.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { AdapterDescriptionUnion } from '@streampipes/platform-services';
-import { FormBuilder, FormGroup } from '@angular/forms';
-import { MatStepper } from '@angular/material/stepper';
-
-@Component({
-  selector: 'sp-specific-adapter-configuration',
-  templateUrl: './specific-adapter-configuration.component.html',
-  styleUrls: ['./specific-adapter-configuration.component.scss']
-})
-export class SpecificAdapterConfigurationComponent implements OnInit {
-
-  /**
-   * Adapter description the selected format is added to
-   */
-  @Input() adapterDescription: AdapterDescriptionUnion;
-
-  /**
-   * Cancels the adapter configuration process
-   */
-  @Output() removeSelectionEmitter: EventEmitter<boolean> = new EventEmitter();
-
-  /**
-   * Go to next configuration step when this is complete
-   */
-  @Output() clickNextEmitter: EventEmitter<MatStepper> = new EventEmitter();
-
-  specificAdapterSettingsFormValid: boolean;
-
-  specificAdapterForm: FormGroup;
-
-  constructor(private _formBuilder: FormBuilder) {
-  }
-
-  ngOnInit(): void {
-    // initialize form for validation
-    this.specificAdapterForm = this._formBuilder.group({});
-    this.specificAdapterForm.statusChanges.subscribe((status) => {
-      this.specificAdapterSettingsFormValid = this.specificAdapterForm.valid;
-    });
-
-    // Go directly to event schema configuration when adapter has no configuration properties
-    if (this.adapterDescription.config.length === 0) {
-      this.specificAdapterSettingsFormValid = true;
-    }
-  }
-
-  public removeSelection() {
-    this.removeSelectionEmitter.emit();
-  }
-
-  public clickNext() {
-    this.clickNextEmitter.emit();
-  }
-}
diff --git a/ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.html b/ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.html
deleted file mode 100644
index f5fabf7..0000000
--- a/ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div [formGroup]="startAdapterForm">
-    <div class="assemblyOptions sp-blue-bg">
-        <h4>Adapter settings</h4>
-    </div>
-
-    <div class="sp-blue-border padding" style="padding: 15px; margin-bottom: 2%;">
-        <div fxLayoutAlign="center" fxLayout="column" fxFlex="100">
-            <mat-form-field color="accent">
-                <input formControlName="adapterName"
-                       matInput id="input-AdapterName" placeholder="Adapter Name"
-                       data-cy="sp-adapter-name" required>
-            </mat-form-field>
-            <mat-form-field color="accent">
-                <input matInput id="input-AdapterDescription" [ngModelOptions]="{standalone: true}"
-                       placeholder="Adapter Description" [(ngModel)]="adapterDescription.description">
-            </mat-form-field>
-
-            <mat-checkbox [(ngModel)]="removeDuplicates"
-                          [ngModelOptions]="{standalone: true}"
-                          data-cy="connect-remove-duplicates-box">Remove Duplicates
-            </mat-checkbox>
-            <mat-form-field *ngIf="removeDuplicates" color="accent">
-                <input matInput id="input-removeDuplicatesTime"
-                       [ngModelOptions]="{standalone: true}" placeholder="Remove Duplicates Time Window"
-                       [(ngModel)]="removeDuplicatesTime"
-                       data-cy="connect-remove-duplicates-input">
-            </mat-form-field>
-
-            <mat-checkbox [(ngModel)]="eventRateReduction"
-                          [ngModelOptions]="{standalone: true}"
-                          matTooltip="Send maximum one event in the specified time window"
-                          data-cy="connect-reduce-event-rate-box">Reduce the event rate
-            </mat-checkbox>
-            <mat-form-field *ngIf="eventRateReduction" color="accent">
-                <input type="number" matInput id="input-evenRateTime"
-                       [ngModelOptions]="{standalone: true}" [(ngModel)]="eventRateTime"
-                       placeholder="Time Window (Milliseconds)" matTooltipPosition="above"
-                       data-cy="connect-reduce-event-input">
-            </mat-form-field>
-            <mat-form-field *ngIf="eventRateReduction" color="accent">
-                <mat-label>Event Aggregation</mat-label>
-                <mat-select [(ngModel)]="eventRateMode" [ngModelOptions]="{standalone: true}">
-                    <mat-option class="md-elevation-z1" style="background: white;"
-                                matTooltip="Last Event in Time Window" value="none">
-                        None
-                    </mat-option>
-                </mat-select>
-            </mat-form-field>
-
-            <!-- Start pipeline template to store raw events in data lake -->
-            <mat-checkbox [(ngModel)]="saveInDataLake"
-                          (change)="findDefaultTimestamp($event)"
-                          [ngModelOptions]="{standalone: true}"
-                          data-cy="sp-store-in-datalake">
-                Store in Datalake
-            </mat-checkbox>
-            <mat-form-field *ngIf="saveInDataLake" color="accent">
-                <mat-label>Select Time Field</mat-label>
-                <mat-select [(ngModel)]="dataLakeTimestampField"
-                            [ngModelOptions]="{standalone: true}"
-                            data-cy="sp-store-in-datalake-timestamp">
-                    <mat-option class="md-elevation-z1" style="background: white;"
-                                *ngFor="let timestampField of eventSchema.eventProperties | timestampFilter"
-                                [value]="timestampField.runtimeName">
-                        {{timestampField.runtimeName}}
-                    </mat-option>
-                </mat-select>
-            </mat-form-field>
-        </div>
-    </div>
-
-    <div fxLayoutAlign="end">
-        <button class="mat-basic" mat-raised-button (click)="removeSelection()">Cancel</button>
-        <button style="margin-left:10px;" class="mat-basic stepper-button" mat-raised-button (click)="goBack()">Back
-        </button>
-        <button [disabled]="!(startAdapterSettingsFormValid)" mat-raised-button id="button-startAdapter"
-                color="accent" (click)="startAdapter()" mat-button style="margin-left:10px;">
-            Start Adapter
-        </button>
-    </div>
-</div>
-
diff --git a/ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.scss b/ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.scss
deleted file mode 100644
index 58ba04b..0000000
--- a/ui/src/app/connect/components/start-adapter-configuration/start-adapter-configuration.component.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
diff --git a/ui/src/app/connect/connect.component.css b/ui/src/app/connect/connect.component.css
deleted file mode 100644
index 58ba04b..0000000
--- a/ui/src/app/connect/connect.component.css
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
diff --git a/ui/src/app/connect/connect.component.ts b/ui/src/app/connect/connect.component.ts
deleted file mode 100644
index 7313e1d..0000000
--- a/ui/src/app/connect/connect.component.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *    http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- *

- */

-

-import { Component } from '@angular/core';

-import { AdapterDescriptionUnion } from '@streampipes/platform-services';

-

-@Component({

-  selector: 'sp-connect',

-  templateUrl: './connect.component.html',

-  styleUrls: ['./connect.component.css'],

-})

-export class ConnectComponent {

-  newAdapterFromDescription: AdapterDescriptionUnion;

-

-  selectAdapter(adapterDescription: AdapterDescriptionUnion) {

-    this.newAdapterFromDescription = adapterDescription;

-  }

-

-  removeSelection() {

-    this.newAdapterFromDescription = undefined;

-  }

-}

diff --git a/ui/src/app/connect/connect.module.ts b/ui/src/app/connect/connect.module.ts
index cad1e33..8d7bc12 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -17,18 +17,15 @@
  */
 
 import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
 import { FlexLayoutModule } from '@angular/flex-layout';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatGridListModule } from '@angular/material/grid-list';
 import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
 
-import { ConnectComponent } from './connect.component';
 import { NewAdapterComponent } from './components/new-adapter/new-adapter.component';
-
-import { EditEventPropertyPrimitiveComponent } from './dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component';
-import { EventSchemaComponent } from './components/schema-editor/event-schema/event-schema.component';
+import { EventSchemaComponent } from './components/new-adapter/schema-editor/event-schema/event-schema.component';
 
 import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
 
@@ -42,114 +39,147 @@
 import { ConnectService } from './services/connect.service';
 import { AdapterDescriptionComponent } from './components/data-marketplace/adapter-description/adapter-description.component';
 import { DataMarketplaceComponent } from './components/data-marketplace/data-marketplace.component';
-import { DataMarketplaceService } from './services/data-marketplace.service';
-import { FormatItemComponent } from './components/format-item/format-item.component';
-import { FormatListComponent } from './components/format-list/format-list.component';
+import { FormatItemComponent } from './components/new-adapter/format-configuration/format-item/format-item.component';
+import { FormatListComponent } from './components/new-adapter/format-configuration/format-list/format-list.component';
 import { IconService } from './services/icon.service';
 import { UnitProviderService } from './services/unit-provider.service';
 
 
-import { FilterPipe } from './filter/filter.pipe';
+import { AdapterFilterPipe } from './filter/adapter-filter.pipe';
 import { AdapterExportDialog } from './dialog/adapter-export/adapter-export-dialog.component';
 import { AdapterUploadDialog } from './dialog/adapter-upload/adapter-upload-dialog.component';
-import { EditEventPropertyListComponent } from './dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component';
 import { TimestampPipe } from './filter/timestamp.pipe';
 import { MatChipsModule } from '@angular/material/chips';
 import { MatSliderModule } from '@angular/material/slider';
 import { TreeModule } from '@circlon/angular-tree-component';
 import { XsService } from '../NS/xs.service';
-import { EditDataTypeComponent } from './dialog/edit-event-property/components/edit-data-type/edit-data-type.component';
-import { EditTimestampPropertyComponent } from './dialog/edit-event-property/components/edit-timestamp-property/edit-timestamp-property.component';
+import { EditDataTypeComponent } from './dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component';
+import { EditTimestampPropertyComponent } from './dialog/edit-event-property/components/edit-value-transformation/edit-timestamp-property/edit-timestamp-property.component';
 import { EditUnitTransformationComponent } from './dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component';
 import { EditEventPropertyComponent } from './dialog/edit-event-property/edit-event-property.component';
 import { PipelineElementRuntimeInfoComponent } from './components/runtime-info/pipeline-element-runtime-info.component';
-import { EventPropertyRowComponent } from './components/schema-editor/event-property-row/event-property-row.component';
-import { EventSchemaPreviewComponent } from './components/schema-editor/event-schema-preview/event-schema-preview.component';
+import { EventPropertyRowComponent } from './components/new-adapter/schema-editor/event-property-row/event-property-row.component';
+import { EventSchemaPreviewComponent } from './components/new-adapter/schema-editor/event-schema-preview/event-schema-preview.component';
 import { CoreUiModule } from '../core-ui/core-ui.module';
 // tslint:disable-next-line:max-line-length
-import { EditCorrectionValueComponent } from './dialog/edit-event-property/components/edit-correction-value/edit-correction-value.component';
-import { ExistingAdaptersComponent } from './components/data-marketplace/existing-adapters/existing-adapters.component';
+import { EditCorrectionValueComponent } from './dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component';
+import { ExistingAdaptersComponent } from './components/existing-adapters/existing-adapters.component';
 // tslint:disable-next-line:max-line-length
-import { SpecificAdapterConfigurationComponent } from './components/specific-adapter-configuration/specific-adapter-configuration.component';
+import { SpecificAdapterConfigurationComponent } from './components/new-adapter/specific-adapter-configuration/specific-adapter-configuration.component';
 import { ConfigurationGroupComponent } from './components/configuration-group/configuration-group.component';
-import { FormatConfigurationComponent } from './components/format-configuration/format-configuration.component';
-import { GenericAdapterConfigurationComponent } from './components/generic-adapter-configuration/generic-adapter-configuration.component';
-import { ErrorMessageComponent } from './components/schema-editor/error-message/error-message.component';
-import { LoadingMessageComponent } from './components/schema-editor/loading-message/loading-message.component';
-import { SchemaEditorHeaderComponent } from './components/schema-editor/schema-editor-header/schema-editor-header.component';
-import { StartAdapterConfigurationComponent } from './components/start-adapter-configuration/start-adapter-configuration.component';
+import { FormatConfigurationComponent } from './components/new-adapter/format-configuration/format-configuration.component';
+import { GenericAdapterConfigurationComponent } from './components/new-adapter/generic-adapter-configuration/generic-adapter-configuration.component';
+import { ErrorMessageComponent } from './components/new-adapter/schema-editor/error-message/error-message.component';
+import { LoadingMessageComponent } from './components/new-adapter/schema-editor/loading-message/loading-message.component';
+import { SchemaEditorHeaderComponent } from './components/new-adapter/schema-editor/schema-editor-header/schema-editor-header.component';
+import { StartAdapterConfigurationComponent } from './components/new-adapter/start-adapter-configuration/start-adapter-configuration.component';
 import { DeleteAdapterDialogComponent } from './dialog/delete-adapter-dialog/delete-adapter-dialog.component';
 import { PlatformServicesModule } from '@streampipes/platform-services';
-import { FormatItemJsonComponent } from './components/format-item-json/format-item-json.component';
+import { FormatItemJsonComponent } from './components/new-adapter/format-configuration/format-item-json/format-item-json.component';
+import { RouterModule } from '@angular/router';
+import { SharedUiModule } from '@streampipes/shared-ui';
+import { SpConnectFilterToolbarComponent } from './components/filter-toolbar/filter-toolbar.component';
+import { EditSchemaTransformationComponent } from './dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component';
+import { EditValueTransformationComponent } from './dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component';
+import { SpEpSettingsSectionComponent } from './dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component';
+import { SpAdapterOptionsPanelComponent } from './components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component';
+import { SpAdapterTemplateDialogComponent } from './dialog/adapter-template/adapter-template-dialog.component';
+import { JsonPrettyPrintPipe } from './filter/json-pretty-print.pipe';
+import { MatSnackBarModule } from '@angular/material/snack-bar';
 
 @NgModule({
-    imports: [
-        CoreUiModule,
-        FormsModule,
-        ReactiveFormsModule,
-        CommonModule,
-        FlexLayoutModule,
-        MatGridListModule,
-        CustomMaterialModule,
-        MatProgressSpinnerModule,
-        MatChipsModule,
-        MatInputModule,
-        MatFormFieldModule,
-        MatSliderModule,
-        PlatformServicesModule,
-        CoreUiModule,
-        TreeModule
-    ],
-    exports: [
-        PipelineElementRuntimeInfoComponent
-    ],
-    declarations: [
-        AdapterDescriptionComponent,
-        AdapterExportDialog,
-        AdapterStartedDialog,
-        AdapterUploadDialog,
-        ConnectComponent,
-        DataMarketplaceComponent,
-        DeleteAdapterDialogComponent,
-        EventSchemaComponent,
-        EditEventPropertyPrimitiveComponent,
-        EditEventPropertyComponent,
-        EventPropertyRowComponent,
-        EditEventPropertyListComponent,
-        EditUnitTransformationComponent,
-        EditTimestampPropertyComponent,
-        EditDataTypeComponent,
-        EventSchemaPreviewComponent,
-        ExistingAdaptersComponent,
-        FilterPipe,
-        FormatItemComponent,
-        FormatListComponent,
-        NewAdapterComponent,
-        PipelineElementRuntimeInfoComponent,
-        TimestampPipe,
-        EditCorrectionValueComponent,
-        FormatConfigurationComponent,
-        GenericAdapterConfigurationComponent,
-        SpecificAdapterConfigurationComponent,
-        ConfigurationGroupComponent,
-        ErrorMessageComponent,
-        LoadingMessageComponent,
-        SchemaEditorHeaderComponent,
-        StartAdapterConfigurationComponent,
-        FormatItemJsonComponent
-    ],
-    providers: [
-        RestService,
-        ConnectService,
-        DataTypesService,
-        TransformationRuleService,
-        StaticPropertyUtilService,
-        DataMarketplaceService,
-        IconService,
-        UnitProviderService,
-        TimestampPipe,
-        XsService
-    ]
+  imports: [
+    CoreUiModule,
+    FormsModule,
+    ReactiveFormsModule,
+    CommonModule,
+    FlexLayoutModule,
+    MatGridListModule,
+    CustomMaterialModule,
+    MatProgressSpinnerModule,
+    MatChipsModule,
+    MatInputModule,
+    MatFormFieldModule,
+    MatSliderModule,
+    MatSnackBarModule,
+    PlatformServicesModule,
+    CoreUiModule,
+    TreeModule,
+    RouterModule.forChild([
+      {
+        path: 'connect',
+        children: [
+          {
+            path: '',
+            component: ExistingAdaptersComponent,
+            pathMatch: 'full'
+          },
+          {
+            path: 'create',
+            component: DataMarketplaceComponent,
+          },
+          {
+            path: 'create/:appId',
+            component: NewAdapterComponent,
+          }]
+      }]),
+    SharedUiModule
+  ],
+  exports: [
+    PipelineElementRuntimeInfoComponent,
+    ErrorMessageComponent
+  ],
+  declarations: [
+    AdapterDescriptionComponent,
+    AdapterExportDialog,
+    AdapterStartedDialog,
+    AdapterUploadDialog,
+    DataMarketplaceComponent,
+    DeleteAdapterDialogComponent,
+    EventSchemaComponent,
+    EditEventPropertyComponent,
+    EventPropertyRowComponent,
+    EditUnitTransformationComponent,
+    EditSchemaTransformationComponent,
+    EditValueTransformationComponent,
+    EditTimestampPropertyComponent,
+    EditDataTypeComponent,
+    EventSchemaPreviewComponent,
+    ExistingAdaptersComponent,
+    AdapterFilterPipe,
+    FormatItemComponent,
+    FormatListComponent,
+    JsonPrettyPrintPipe,
+    NewAdapterComponent,
+    SpAdapterTemplateDialogComponent,
+    PipelineElementRuntimeInfoComponent,
+    TimestampPipe,
+    EditCorrectionValueComponent,
+    FormatConfigurationComponent,
+    GenericAdapterConfigurationComponent,
+    SpecificAdapterConfigurationComponent,
+    ConfigurationGroupComponent,
+    ErrorMessageComponent,
+    LoadingMessageComponent,
+    SchemaEditorHeaderComponent,
+    SpEpSettingsSectionComponent,
+    StartAdapterConfigurationComponent,
+    FormatItemJsonComponent,
+    SpConnectFilterToolbarComponent,
+    SpAdapterOptionsPanelComponent
+  ],
+  providers: [
+    RestService,
+    ConnectService,
+    DataTypesService,
+    TransformationRuleService,
+    StaticPropertyUtilService,
+    IconService,
+    UnitProviderService,
+    TimestampPipe,
+    XsService
+  ],
+  schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
 })
 export class ConnectModule {
 }
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/connect.routes.ts
similarity index 75%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/connect/connect.routes.ts
index 58ba04b..9ddbb18 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/connect.routes.ts
@@ -16,3 +16,11 @@
  *
  */
 
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+
+export class SpConnectRoutes {
+
+  static BASE: SpBreadcrumbItem = {label: 'Connect', link: ['connect']};
+  static CREATE: SpBreadcrumbItem = {label: 'New Adapter', link: ['connect', 'create']};
+
+}
diff --git a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
index e4c3e67..a6aa9a0 100644
--- a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
+++ b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
@@ -42,7 +42,7 @@
   adapterInstalled = false;
   public adapterStatus: Message;
   public streamDescription: SpDataStream;
-  private pollingActive = false;
+  pollingActive = false;
   public runtimeData: any;
   public isSetAdapter = false;
   public isTemplate = false;
@@ -92,14 +92,6 @@
               const pipelineName = 'Persist ' + this.adapter.name;
 
               let indexName = this.adapter.name
-                .toLowerCase()
-                .replace(/ /g, '')
-                .replace(/\./g, '');
-
-              // Ensure that index name is no number
-              if (this.isNumber(indexName)) {
-                indexName = 'sp' + indexName;
-              }
 
               const pipelineInvocation = PipelineInvocationBuilder
                 .create(res)
@@ -127,9 +119,4 @@
     this.shepherdService.trigger('confirm_adapter_started_button');
   }
 
-  private isNumber(value: string | number): boolean {
-    return ((value != null) &&
-      (value !== '') &&
-      !isNaN(Number(value.toString())));
-  }
 }
diff --git a/ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.html b/ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.html
new file mode 100644
index 0000000..7d39534
--- /dev/null
+++ b/ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.html
@@ -0,0 +1,39 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100"
+             fxLayout="column">
+            <pipeline-element-template-config [staticProperties]="configs"
+                                              [template]="template"
+                                              [templateConfigs]="templateConfigs"
+                                              [appId]="appId">
+            </pipeline-element-template-config>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <button mat-button mat-raised-button color="accent"
+                (click)="saveTemplate()"
+                style="margin-right: 10px;">
+            Create template
+        </button>
+        <button mat-button mat-raised-button class="mat-basic" (click)="dialogRef.close()">Close</button>
+    </div>
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.scss
similarity index 93%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.scss
index 58ba04b..fddade7 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.scss
@@ -16,3 +16,4 @@
  *
  */
 
+@import '../../../../scss/sp/sp-dialog.scss';
diff --git a/ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.ts b/ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.ts
new file mode 100644
index 0000000..76f3ce7
--- /dev/null
+++ b/ui/src/app/connect/dialog/adapter-template/adapter-template-dialog.component.ts
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import {
+  PipelineElementTemplate,
+  PipelineElementTemplateConfig,
+  PipelineElementTemplateService,
+  StaticPropertyUnion
+} from '@streampipes/platform-services';
+import { DialogRef } from '@streampipes/shared-ui';
+
+@Component({
+  selector: 'sp-adapter-template-dialog',
+  templateUrl: './adapter-template-dialog.component.html',
+  styleUrls: ['./adapter-template-dialog.component.scss']
+})
+export class SpAdapterTemplateDialogComponent implements OnInit {
+
+  @Input()
+  configs: StaticPropertyUnion[];
+
+  @Input()
+  appId: string;
+
+  template: PipelineElementTemplate;
+  templateConfigs: Map<string, any> = new Map();
+
+  constructor(public dialogRef: DialogRef<SpAdapterTemplateDialogComponent>,
+              private pipelineElementTemplateService: PipelineElementTemplateService) {
+
+  }
+
+  ngOnInit(): void {
+    this.template = new PipelineElementTemplate();
+  }
+
+  saveTemplate() {
+    this.template.templateConfigs = this.convert(this.templateConfigs);
+    this.pipelineElementTemplateService.storePipelineElementTemplate(this.template).subscribe(result => {
+      this.dialogRef.close(true);
+    });
+  }
+
+  convert(templateConfigs: Map<string, any>): any {
+    const configs: { [index: string]: PipelineElementTemplateConfig } = {};
+    templateConfigs.forEach((value, key) => {
+      configs[key] = new PipelineElementTemplateConfig();
+      configs[key].editable = value.editable;
+      configs[key].displayed = value.displayed;
+      configs[key].value = value.value;
+    });
+    return configs;
+  }
+
+}
diff --git a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html
index 9f8beed..72ca41f 100644
--- a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html
+++ b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html
@@ -33,7 +33,7 @@
             <div fxFlex="100" fxLayoutAlign="center center" fxLayout="column">
                 <button mat-button mat-raised-button color="accent"
                         (click)="deleteAdapter()"
-                        data-cy="delete-adapter">Delete
+                        data-cy="delete-adapter-confirmation">Delete
                     adapter
                 </button>
             </div>
diff --git a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.ts b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.ts
index ce05016..dc61d38 100644
--- a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.ts
+++ b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.ts
@@ -17,9 +17,8 @@
  */
 
 import { Component, Input } from '@angular/core';
-import { AdapterDescriptionUnion } from '@streampipes/platform-services';
+import { AdapterDescriptionUnion, AdapterService } from '@streampipes/platform-services';
 import { DialogRef } from '@streampipes/shared-ui';
-import { DataMarketplaceService } from '../../services/data-marketplace.service';
 
 @Component({
     selector: 'sp-delete-adapter-dialog',
@@ -37,7 +36,7 @@
     numberOfPipelinesWithAdapter = 0;
 
     constructor(private dialogRef: DialogRef<DeleteAdapterDialogComponent>,
-                private dataMarketplaceService: DataMarketplaceService) {
+                private dataMarketplaceService: AdapterService) {
     }
 
     close(refreshAdapters: boolean) {
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.scss b/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.scss
deleted file mode 100644
index 58ba04b..0000000
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.ts
deleted file mode 100644
index 6c95c13..0000000
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-list/edit-event-property-list.component.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, Input } from '@angular/core';
-
-@Component({
-  selector: 'sp-edit-event-property-list',
-  templateUrl: './edit-event-property-list.component.html',
-  styleUrls: ['./edit-event-property-list.component.scss']
-})
-export class EditEventPropertyListComponent {
-
-  constructor() { }
-
-  @Input() cachedProperty: any;
-
-}
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.html
deleted file mode 100644
index def4039..0000000
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div class="divBorder">
-    <sp-edit-timestamp-property
-            *ngIf="isTimestampProperty"
-            [cachedProperty]= "cachedProperty"
-            showEditTimestampProperty="!isTimestampProperty">
-    </sp-edit-timestamp-property>
-
-    <sp-edit-data-type
-            *ngIf="!isTimestampProperty"
-            [cachedProperty]= "cachedProperty"
-            (dataTypeChanged)="setShowUnitTransformation()">
-    </sp-edit-data-type>
-
-    <sp-edit-unit-transformation
-            *ngIf="!isTimestampProperty"
-            [cachedProperty]= "cachedProperty"
-            [showUnitTransformation]="!hideUnitTransformation">
-    </sp-edit-unit-transformation>
-
-    <div fxLayout="row" fxLayoutAlign="start" *ngIf="addedByUser">
-        <mat-form-field  class="doubleWidth">
-            <input matInput
-                   placeholder="Static Value"
-                   name="static_value"
-                   id="static_value"
-                   data-cy="connect-edit-field-static-value"
-                [(ngModel)]="cachedProperty.staticValue">
-        </mat-form-field>
-    </div>
-
-</div>
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.scss b/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.scss
deleted file mode 100644
index 7a945ed..0000000
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.scss
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-.doubleWidth {
-  width: 370px !important;
-}
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.ts
deleted file mode 100644
index 182685e..0000000
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-event-property-primitive/edit-event-property-primitive.component.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { DataTypesService } from '../../../../services/data-type.service';
-
-@Component({
-  selector: 'sp-edit-event-property-primitive',
-  templateUrl: './edit-event-property-primitive.component.html',
-  styleUrls: ['./edit-event-property-primitive.component.scss']
-})
-export class EditEventPropertyPrimitiveComponent implements OnInit {
-
-  @Input() cachedProperty: any;
-  @Input() index: number;
-  @Input() isTimestampProperty: boolean;
-  @Output() isNumericDataType = new EventEmitter<boolean>();
-
-  hideUnitTransformation: boolean;
-
-  addedByUser: boolean;
-
-  constructor(private dataTypesService: DataTypesService) {
-  }
-
-  ngOnInit(): void {
-    this.setShowUnitTransformation();
-    this.addedByUser = this.staticValueAddedByUser();
-    if (!this.cachedProperty.staticValue) {
-      this.cachedProperty.staticValue = '';
-    }
-  }
-
-  setShowUnitTransformation() {
-    this.hideUnitTransformation = this.isTimestampProperty ||
-      !this.dataTypesService.isNumeric(this.cachedProperty.runtimeType);
-
-    if (this.dataTypesService.isNumeric(this.cachedProperty.runtimeType)) {
-      this.isNumericDataType.emit(true);
-    } else {
-      this.isNumericDataType.emit(false);
-    }
-  }
-
-  staticValueAddedByUser() {
-    return this.cachedProperty.elementId.startsWith('http://eventProperty.de/staticValue/');
-  }
-
-}
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-data-type/edit-data-type.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component.html
similarity index 89%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-data-type/edit-data-type.component.html
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component.html
index 7e8c9f4..05ed0e3 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-data-type/edit-data-type.component.html
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component.html
@@ -16,8 +16,9 @@
   ~
   -->
 
-<mat-form-field class="doubleWidth" color="accent">
-    <mat-select placeholder="Runtime Type"
+<mat-form-field class="w-100" color="accent" fxFlex="100">
+    <mat-label>Field data type</mat-label>
+    <mat-select placeholder="Data Type"
                 [(ngModel)]="cachedProperty.runtimeType"
                 (selectionChange)="valueChanged()"
                 data-cy="connect-change-runtime-type">
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-data-type/edit-data-type.component.scss b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component.scss
similarity index 100%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-data-type/edit-data-type.component.scss
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component.scss
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-data-type/edit-data-type.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component.ts
similarity index 94%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-data-type/edit-data-type.component.ts
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component.ts
index 77e0d82..b303e8c 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-data-type/edit-data-type.component.ts
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-data-type/edit-data-type.component.ts
@@ -17,7 +17,7 @@
  */
 
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { DataTypesService } from '../../../../services/data-type.service';
+import { DataTypesService } from '../../../../../services/data-type.service';
 
 @Component({
   selector: 'sp-edit-data-type',
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html
new file mode 100644
index 0000000..98cc26f
--- /dev/null
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html
@@ -0,0 +1,80 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="general-options-panel" fxLayout="column">
+    <div class="general-options-header"><span>Schema</span></div>
+    <sp-ep-settings-section sectionTitle="Field runtime name"
+                            sectionDescription="Identifies the field in the underlying runtime format">
+        <div attr.id="input-runtime-name-{{cachedProperty.label}}"
+             fxFlex="100">
+            <mat-form-field class="w-100" color="accent">
+                <mat-label>Field runtime name</mat-label>
+                <input matInput
+                       placeholder="RuntimeName"
+                       name="runtimename"
+                       id="runtimename"
+                       data-cy="connect-edit-field-runtime-name"
+                       [(ngModel)]="cachedProperty.runtimeName">
+            </mat-form-field>
+        </div>
+    </sp-ep-settings-section>
+
+    <sp-ep-settings-section sectionTitle="Field semantic type"
+                            sectionDescription="Identifies field semantics, e.g., oil temperature"
+                            fxLayout="column"
+                            fxFlex="100"
+                            *ngIf="isPrimitiveProperty">
+        <div fxFlex="100" fxLayout="column" style="margin-bottom: 5px;">
+            <mat-checkbox name="timestampCheckbox"
+                          (change)="editTimestampDomainProperty($event.checked)"
+                          [checked]="isTimestampProperty"
+                          color="accent"
+                          data-cy="sp-mark-as-timestamp">
+                Mark as timestamp
+            </mat-checkbox>
+        </div>
+        <div *ngIf="isPrimitiveProperty" fxFlex="100" fxLayout="column">
+            <mat-form-field class="w-100" color="accent" fxFlex="100">
+                <input matInput placeholder="Semantic Type"
+                       class="dmainProperty"
+                       name="domainproperty"
+                       id="domainproperty"
+                       [(ngModel)]="cachedProperty.domainProperties[0]"
+                       [matAutocomplete]="st"
+                       [disabled]="isTimestampProperty"
+                       [matAutocompleteDisabled]="isTimestampProperty"
+                       [formControl]="domainPropertyControl">
+                <mat-autocomplete #st="matAutocomplete" [panelWidth]="'300px'">
+                    <mat-option *ngFor="let semanticType of semanticTypes | async" [value]="semanticType"
+                                style="font-size: 10pt;">
+                        {{semanticType}}
+                    </mat-option>
+                </mat-autocomplete>
+            </mat-form-field>
+        </div>
+    </sp-ep-settings-section>
+
+    <sp-ep-settings-section sectionTitle="Field data type"
+                            sectionDescription="The data type of the field values"
+                            *ngIf="!isTimestampProperty">
+        <sp-edit-data-type
+                [cachedProperty]="cachedProperty"
+                (dataTypeChanged)="dataTypeChanged.emit($event)">
+        </sp-edit-data-type>
+    </sp-ep-settings-section>
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.scss
similarity index 99%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.scss
index 58ba04b..13cbc4a 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.scss
@@ -15,4 +15,3 @@
  * limitations under the License.
  *
  */
-
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts
new file mode 100644
index 0000000..b58d499
--- /dev/null
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { EventPropertyUnion, SemanticTypesService } from '@streampipes/platform-services';
+import { debounceTime, distinctUntilChanged, startWith, switchMap } from 'rxjs/operators';
+import { FormControl } from '@angular/forms';
+import { Observable } from 'rxjs';
+
+@Component({
+  selector: 'sp-edit-schema-transformation',
+  templateUrl: './edit-schema-transformation.component.html',
+  styleUrls: ['./edit-schema-transformation.component.scss']
+})
+export class EditSchemaTransformationComponent implements OnInit {
+
+  soTimestamp = 'http://schema.org/DateTime';
+
+  @Input()
+  cachedProperty: any;
+
+  @Input() isTimestampProperty: boolean;
+  @Input() isNestedProperty: boolean;
+  @Input() isListProperty: boolean;
+  @Input() isPrimitiveProperty: boolean;
+
+  @Output() dataTypeChanged = new EventEmitter<boolean>();
+  @Output() timestampSemanticsChanged = new EventEmitter<boolean>();
+
+  domainPropertyControl = new FormControl();
+  semanticTypes: Observable<string[]>;
+
+  constructor(private semanticTypesService: SemanticTypesService) {
+
+  }
+
+  ngOnInit(): void {
+    this.semanticTypes = this.domainPropertyControl.valueChanges
+      .pipe(
+        startWith(''),
+        debounceTime(400),
+        distinctUntilChanged(),
+        switchMap(val => {
+          return val ? this.semanticTypesService.getSemanticTypes(val) : [];
+        })
+      );
+  }
+
+  editTimestampDomainProperty(checked: boolean) {
+    if (checked) {
+      this.isTimestampProperty = true;
+      this.cachedProperty.domainProperties = [this.soTimestamp];
+      this.cachedProperty.propertyScope = 'HEADER_PROPERTY';
+      this.cachedProperty.runtimeType = 'http://www.w3.org/2001/XMLSchema#long';
+    } else {
+      this.cachedProperty.domainProperties = [];
+      this.cachedProperty.propertyScope = 'MEASUREMENT_PROPERTY';
+      this.isTimestampProperty = false;
+    }
+    this.timestampSemanticsChanged.emit(this.isTimestampProperty);
+  }
+
+}
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component.html
index edc51e2..2d25621 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component.html
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component.html
@@ -16,57 +16,70 @@
   ~
   -->
 
-<div fxLayout="row" fxLayoutAlign="start" *ngIf="showUnitTransformation">
-    <div class="form-group" fxFlexAlign="center" style="width: 155px">
-        <mat-form-field *ngIf="!hadMeasurementUnit" class="example-full-width" style="width: 155px" color="accent">
-            <input matInput
-                   placeholder="Unit"
-                   [matAutocomplete]="auto"
-                   [formControl]="stateCtrl"
-                   [attr.disabled]="transformUnitEnable ? '' : null"
-                   data-cy="connect-schema-unit-from-dropdown">
-            <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn" [panelWidth]="'300px'">
-                <mat-option
-                        *ngFor="let unit of filteredUnits | async"
-                        [value]="unit.label"
-                        [attr.data-cy]="unit.resource">
-                    {{unit.label}}
-                </mat-option>
-            </mat-autocomplete>
-        </mat-form-field>
-        <mat-form-field *ngIf="hadMeasurementUnit"
-                        class="example-full-width"
-                        style="width: 155px"
-                        color="accent">
-            <input matInput
-                   placeholder="Unit"
-                   disabled
-                   [(ngModel)]="oldMeasurementUnitDipsplay"
-                   data-cy="connect-schema-unit-from-input">
-        </mat-form-field>
+<div class="general-options-panel" fxLayout="column">
+    <span class="general-options-header">Unit Transformation</span>
 
-    </div>
-    <button mat-button
-            (click)="transformUnit()"
-            color="accent"
-            class="form-group"
-            fxFlexAlign="center"
-            style="min-width: 60px; max-width: 60px"
-            data-cy="connect-schema-unit-transform-btn">
-        <mat-icon *ngIf="!transformUnitEnable">arrow_forward</mat-icon>
-        <mat-icon *ngIf="transformUnitEnable" style="transform: rotate(180deg)">arrow_forward</mat-icon>
-    </button>
-    <mat-form-field class="example-full-width" style="width: 155px" *ngIf="transformUnitEnable" color="accent">
-        <mat-select placeholder="New Unit"
-                    [(ngModel)]="selectUnit"
-                    [formControl]="newUnitStateCtrl"
-                    [compareWith]="compareFn"
-                    data-cy="connect-schema-unit-to-dropdown">
-            <mat-option *ngFor="let unit of possibleUnitTransformations" [value]="unit"
-                        (click)="changeTargetUnit(unit)">
-                {{unit.label}}
-            </mat-option>
-        </mat-select>
-    </mat-form-field>
+    <sp-ep-settings-section sectionTitle="Unit conversion"
+                            sectionDescription="Converts the field value from the given measurement unit to the provided target unit"
+                            fxFlex="100"
+                            *ngIf="isPrimitiveProperty && !isTimestampProperty && isNumericProperty">
+        <div fxLayout="row">
+            <div class="w-100" fxLayoutAlign="start center" fxFlex="45">
+                <mat-form-field *ngIf="!hadMeasurementUnit" class="w-100" color="accent" fxFlex="100">
+                    <input matInput
+                           placeholder="Unit"
+                           [matAutocomplete]="auto"
+                           [formControl]="stateCtrl"
+                           [attr.disabled]="transformUnitEnable ? '' : null"
+                           data-cy="connect-schema-unit-from-dropdown">
+                    <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn" [panelWidth]="'300px'">
+                        <mat-option
+                                *ngFor="let unit of filteredUnits | async"
+                                [value]="unit.label"
+                                [attr.data-cy]="unit.resource">
+                            {{unit.label}}
+                        </mat-option>
+                    </mat-autocomplete>
+                </mat-form-field>
+                <mat-form-field *ngIf="hadMeasurementUnit"
+                                class="example-full-width"
+                                style="width: 155px"
+                                color="accent">
+                    <input matInput
+                           placeholder="Unit"
+                           disabled
+                           [(ngModel)]="oldMeasurementUnitDipsplay"
+                           data-cy="connect-schema-unit-from-input">
+                </mat-form-field>
+
+            </div>
+            <div fxFlex="10" fxLayoutAlign="center center">
+                <button mat-button
+                        (click)="transformUnit()"
+                        color="accent"
+                        class="form-group"
+                        fxFlexAlign="center"
+                        style="min-width: 60px; max-width: 60px"
+                        data-cy="connect-schema-unit-transform-btn">
+                    <mat-icon *ngIf="!transformUnitEnable">arrow_forward</mat-icon>
+                    <mat-icon *ngIf="transformUnitEnable" style="transform: rotate(180deg)">arrow_forward</mat-icon>
+                </button>
+            </div>
+            <div fxFlex="45" fxLayoutAlign="start center">
+                <mat-form-field class="w-100" *ngIf="transformUnitEnable" color="accent" fxFlex="100">
+                    <mat-select placeholder="New Unit"
+                                [(ngModel)]="selectUnit"
+                                [formControl]="newUnitStateCtrl"
+                                [compareWith]="compareFn"
+                                data-cy="connect-schema-unit-to-dropdown">
+                        <mat-option *ngFor="let unit of possibleUnitTransformations" [value]="unit"
+                                    (click)="changeTargetUnit(unit)">
+                            {{unit.label}}
+                        </mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+        </div>
+    </sp-ep-settings-section>
 </div>
 
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component.ts
index 3c04151..a796c5c 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component.ts
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-unit-transformation/edit-unit-transformation.component.ts
@@ -32,6 +32,13 @@
 export class EditUnitTransformationComponent implements OnInit {
 
   @Input() cachedProperty: any;
+
+  @Input() isTimestampProperty: boolean;
+  @Input() isNestedProperty: boolean;
+  @Input() isListProperty: boolean;
+  @Input() isPrimitiveProperty: boolean;
+  @Input() isNumericProperty: boolean;
+
   @Input() showUnitTransformation: boolean;
 
   private transformUnitEnable = false;
@@ -133,5 +140,16 @@
     (this.cachedProperty as any).measurementUnitTmp = unit.resource;
     this.newUnitStateCtrl.setValue(unit);
   }
+
+  // setShowUnitTransformation() {
+  //   this.hideUnitTransformation = this.isTimestampProperty ||
+  //     !this.dataTypesService.isNumeric(this.cachedProperty.runtimeType);
+  //
+  //   if (this.dataTypesService.isNumeric(this.cachedProperty.runtimeType)) {
+  //     this.isNumericDataType.emit(true);
+  //   } else {
+  //     this.isNumericDataType.emit(false);
+  //   }
+  // }
 }
 
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-correction-value/edit-correction-value.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.html
similarity index 83%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-correction-value/edit-correction-value.component.html
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.html
index 049ebd8..c09542b 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-correction-value/edit-correction-value.component.html
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.html
@@ -17,18 +17,18 @@
   -->
 
 <div fxLayout="row" fxLayoutAlign="start">
-        <div class="form-group" fxFlexAlign="center">
-        <mat-form-field class="example-full-width" style="margin-right: 10px" color="accent">
+    <div fxFlex="70" fxLayoutAlign="start center">
+        <mat-form-field class="w-100" style="margin-right: 10px" color="accent">
             <input matInput
                    name="correction"
                    placeholder="Correction Value"
                    [(ngModel)]="cachedProperty.correctionValue"
                    (change)="valueChanged()"
-                    data-cy="connect-schema-correction-value">
+                   data-cy="connect-schema-correction-value">
         </mat-form-field>
     </div>
-    <div class="form-group" fxFlexAlign="center">
-        <mat-form-field class="example-full-width" color="accent">
+    <div fxFlex="30" fxLayoutAlign="start center">
+        <mat-form-field class="w-100" color="accent">
             <mat-select
                     required
                     placeholder="Math Operator"
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-correction-value/edit-correction-value.component.scss b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.scss
similarity index 100%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-correction-value/edit-correction-value.component.scss
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.scss
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-correction-value/edit-correction-value.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.ts
similarity index 100%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-correction-value/edit-correction-value.component.ts
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.ts
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-timestamp-property/edit-timestamp-property.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-timestamp-property/edit-timestamp-property.component.html
similarity index 75%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-timestamp-property/edit-timestamp-property.component.html
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-timestamp-property/edit-timestamp-property.component.html
index 111b137..12c9ea6 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-timestamp-property/edit-timestamp-property.component.html
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-timestamp-property/edit-timestamp-property.component.html
@@ -17,7 +17,7 @@
   -->
 
 <div fxLayout="row" fxLayoutAlign="start">
-     <mat-form-field class="doubleWidth" color="accent">
+    <mat-form-field class="w-100" color="accent" fxFlex="100">
         <mat-select placeholder="Timestamp converter (unix timestamp)"
                     [(value)]="cachedProperty.timestampTransformationMode"
                     data-cy="connect-timestamp-converter">
@@ -30,17 +30,24 @@
 
 
 <div fxLayout="row" fxLayoutAlign="start">
-    <div class="form-group" fxFlexAlign="center">
-        <mat-form-field class="doubleWidth" *ngIf="cachedProperty.timestampTransformationMode === 'formatString'" color="accent">
-            <input matInput
+    <div class="form-group" fxFlexAlign="center" fxFlex="100">
+        <mat-form-field class="w-100"
+                        *ngIf="cachedProperty.timestampTransformationMode === 'formatString'"
+                        color="accent"
+                        fxFlex="100">
+            <input class="w-100" matInput
                    placeholder="E.g. yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
                    data-cy="connect-timestamp-string-regex"
                    [(ngModel)]="cachedProperty.timestampTransformationFormatString">
         </mat-form-field>
-        <mat-form-field class="doubleWidth" *ngIf="cachedProperty.timestampTransformationMode === 'timeUnit'" color="accent">
+        <mat-form-field class="w-100"
+                        *ngIf="cachedProperty.timestampTransformationMode === 'timeUnit'"
+                        color="accent"
+                        fxFlex="100">
             <mat-select placeholder="Current time unit" [(value)]="selectedTimeMultiplier">
                 <mat-option value="milliseconds" (click)="cachedProperty.timestampTransformationMultiplier = 0">
-                    Milliseconds</mat-option>
+                    Milliseconds
+                </mat-option>
                 <mat-option value="second" (click)="cachedProperty.timestampTransformationMultiplier = 1000">Seconds
                 </mat-option>
             </mat-select>
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-timestamp-property/edit-timestamp-property.component.scss b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-timestamp-property/edit-timestamp-property.component.scss
similarity index 100%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-timestamp-property/edit-timestamp-property.component.scss
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-timestamp-property/edit-timestamp-property.component.scss
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-timestamp-property/edit-timestamp-property.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-timestamp-property/edit-timestamp-property.component.ts
similarity index 100%
rename from ui/src/app/connect/dialog/edit-event-property/components/edit-timestamp-property/edit-timestamp-property.component.ts
rename to ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-timestamp-property/edit-timestamp-property.component.ts
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.html
new file mode 100644
index 0000000..9703ccf
--- /dev/null
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.html
@@ -0,0 +1,55 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="general-options-panel" fxLayout="column">
+    <span class="general-options-header">Value Transformation</span>
+    <sp-ep-settings-section sectionTitle="Timestamp conversion"
+                            sectionDescription="Formula to convert the field value to a UNIX timestamp in milliseconds"
+                            fxLayout="column"
+                            fxFlex="100"
+                            *ngIf="isTimestampProperty">
+        <sp-edit-timestamp-property
+                [cachedProperty]="cachedProperty"
+                showEditTimestampProperty="!isTimestampProperty">
+        </sp-edit-timestamp-property>
+    </sp-ep-settings-section>
+    <sp-ep-settings-section sectionTitle="Value conversion"
+                            sectionDescription="Converts the original field values using the provided formula"
+                            fxLayout="column"
+                            fxFlex="100"
+                            *ngIf="isNumericProperty && !isTimestampProperty">
+        <sp-edit-correction-value
+                [cachedProperty]="cachedProperty">
+            <!--(correctionValueChanged)="enableSaveBtn($event)"-->
+        </sp-edit-correction-value>
+    </sp-ep-settings-section>
+    <sp-ep-settings-section sectionTitle="Static value assignment"
+                            sectionDescription="Assigns a static value to each incoming event"
+                            fxLayout="column"
+                            fxFlex="100"
+                            *ngIf="addedByUser">
+        <mat-form-field class="w-100" fxFlex="100">
+            <input matInput
+                   placeholder="Static Value"
+                   name="static_value"
+                   id="static_value"
+                   data-cy="connect-edit-field-static-value"
+                   [(ngModel)]="cachedProperty.staticValue">
+        </mat-form-field>
+    </sp-ep-settings-section>
+</div>
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.scss
similarity index 99%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.scss
index 58ba04b..13cbc4a 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.scss
@@ -15,4 +15,3 @@
  * limitations under the License.
  *
  */
-
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.ts
new file mode 100644
index 0000000..ec035d9
--- /dev/null
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.ts
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+
+@Component({
+  selector: 'sp-edit-value-transformation',
+  templateUrl: './edit-value-transformation.component.html',
+  styleUrls: ['./edit-value-transformation.component.scss']
+})
+export class EditValueTransformationComponent implements OnInit {
+
+  @Input()
+  cachedProperty: any;
+
+  @Input() isTimestampProperty: boolean;
+  @Input() isNestedProperty: boolean;
+  @Input() isListProperty: boolean;
+  @Input() isPrimitiveProperty: boolean;
+  @Input() isNumericProperty: boolean;
+
+  addedByUser: boolean;
+
+  ngOnInit(): void {
+    this.addedByUser = this.staticValueAddedByUser();
+    if (!this.cachedProperty.staticValue) {
+      this.cachedProperty.staticValue = '';
+    }
+  }
+
+  staticValueAddedByUser() {
+    return this.cachedProperty.elementId.startsWith('http://eventProperty.de/staticValue/');
+  }
+
+}
diff --git a/ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html b/ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.html
similarity index 60%
copy from ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html
copy to ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.html
index 639fd6c..be870a1 100644
--- a/ui/src/app/connect/components/schema-editor/loading-message/loading-message.component.html
+++ b/ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.html
@@ -15,12 +15,17 @@
   ~ limitations under the License.
   ~
   -->
-
-<div fxLayout="column" >
-    <div fxLayoutAlign="center">
-        <mat-spinner fxLayoutAlign="center" style="margin: 10px 0 5px 0" color="accent">Loading</mat-spinner>
+<div fxLayout="column" fxFlex="100">
+    <div fxLayout="row" fxFlex="100" class="ep-settings-section ep-settings-section-border">
+        <div fxFlex="30" style="margin-right: 10px;">
+            <div fxLayout="column" fxFlex="100">
+                <b>{{sectionTitle}}</b>
+                <mat-hint class="description">{{sectionDescription}}</mat-hint>
+            </div>
+        </div>
+        <div fxFlex fxLayout="column">
+            <ng-content fxLayout="column" fxFlex="100"></ng-content>
+        </div>
     </div>
-    <div fxLayoutAlign="center">
-        <h3>Guessing the event schema...</h3>
-    </div>
+<!--    <mat-divider></mat-divider>-->
 </div>
diff --git a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss b/ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.scss
similarity index 84%
copy from ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss
copy to ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.scss
index 2c1a70e..5074a34 100644
--- a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss
+++ b/ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.scss
@@ -16,19 +16,17 @@
  *
  */
 
-@import '../../../../scss/sp/sp-dialog.scss';
-
-.divider {
-  margin-top: 10px;
-  margin-bottom: 10px;
-}
-
-.static-property-panel {
+.ep-settings-section {
   padding-left: 10px;
   margin-bottom: 10px;
   margin-top: 10px;
+  margin-right: 5px;
 }
 
-.static-property-panel-border {
+.ep-settings-section-border {
   border-left:5px solid gray;
 }
+
+.description {
+  font-size: 10px;
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.ts
similarity index 72%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
copy to ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.ts
index 4e64c25..7700e3e 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.ts
+++ b/ui/src/app/connect/dialog/edit-event-property/components/ep-settings-section/ep-settings-section.component.ts
@@ -16,23 +16,24 @@
  *
  */
 
+
 import { Component, Input, OnInit } from '@angular/core';
-import { Notification } from '@streampipes/platform-services';
 
 @Component({
-  selector: 'sp-error-message',
-  templateUrl: './error-message.component.html',
-  styleUrls: ['./error-message.component.scss']
+  selector: 'sp-ep-settings-section',
+  templateUrl: './ep-settings-section.component.html',
+  styleUrls: ['./ep-settings-section.component.scss']
 })
-export class ErrorMessageComponent implements OnInit {
+export class SpEpSettingsSectionComponent implements OnInit {
 
-  @Input() errorMessages: Notification[];
+  @Input()
+  sectionTitle: string;
 
-  showErrorMessage = false;
-
-  constructor() { }
+  @Input()
+  sectionDescription: string;
 
   ngOnInit(): void {
   }
 
+
 }
diff --git a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.html b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.html
index a67a461..132efac 100644
--- a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.html
+++ b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.html
@@ -16,83 +16,103 @@
   ~
   -->
 
-<h2 mat-dialog-title>Edit field {{property.runtimeName}}</h2>
-<mat-dialog-content>
-  <form #propertyForm="ngForm">
-    <div fxLayout="row" fxLayoutAlign="start">
-      <div class="form-group" fxFlexAlign="center">
-        <mat-form-field class="example-full-width" style="margin-right: 10px" color="accent">
-          <input matInput placeholder="Label" name="label" id="label" [(ngModel)]="cachedProperty.label">
-        </mat-form-field>
-      </div>
-      <div attr.id="input-runtime-name-{{cachedProperty.label}}" class="form-group" fxFlexAlign="center">
-        <mat-form-field class="example-full-width" color="accent">
-          <input matInput
-                 placeholder="RuntimeName"
-                 name="runtimename"
-                 id="runtimename"
-                 data-cy="connect-edit-field-runtime-name"
-            [(ngModel)]="cachedProperty.runtimeName">
-        </mat-form-field>
-      </div>
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100"
+             fxLayout="column">
+            <form #propertyForm="ngForm"
+                  fxLayout="column">
+                <div fxLayout="column"
+                     fxLayoutAlign="start"
+                     fxFlex="100">
+                    <div class="general-options-panel"
+                         fxLayout="column"
+                         fxFlex="100">
+                        <span class="general-options-header">Basics</span>
+                        <sp-ep-settings-section sectionTitle="Field label"
+                                                sectionDescription="A label for better readability">
+                            <mat-form-field class="w-100"
+                                            color="accent">
+                                <input matInput
+                                       placeholder="Label"
+                                       name="label"
+                                       id="label"
+                                       [(ngModel)]="cachedProperty.label">
+                            </mat-form-field>
+                        </sp-ep-settings-section>
+                        <sp-ep-settings-section sectionTitle="Field description"
+                                                sectionDescription="A description for better readability">
+                            <mat-form-field class="full-width"
+                                            color="accent">
+                                <textarea matInput
+                                          name="description"
+                                          placeholder="Description"
+                                          id="description"
+                                          [(ngModel)]="cachedProperty.description" cols="20" rows="2">
+                                </textarea>
+                            </mat-form-field>
+                        </sp-ep-settings-section>
+                    </div>
+
+
+                    <sp-edit-schema-transformation [cachedProperty]="cachedProperty"
+                                                   [isTimestampProperty]="isTimestampProperty"
+                                                   [isNestedProperty]="isEventPropertyNested"
+                                                   [isListProperty]="isEventPropertyList"
+                                                   [isPrimitiveProperty]="isEventPropertyPrimitive"
+                                                   *ngIf="!isEventPropertyNested"
+                                                   (dataTypeChanged)="handleDataTypeChange($event)"
+                                                   (timestampSemanticsChanged)="handleTimestampChange($event)"
+                                                   #schemaTransformationComponent>
+
+                    </sp-edit-schema-transformation>
+
+                    <sp-edit-value-transformation [cachedProperty]="cachedProperty"
+                                                  *ngIf="isEventPropertyPrimitive"
+                                                  [isTimestampProperty]="isTimestampProperty"
+                                                  [isNumericProperty]="isNumericProperty"
+                                                  [isNestedProperty]="isEventPropertyNested"
+                                                  [isListProperty]="isEventPropertyList"
+                                                  [isPrimitiveProperty]="isEventPropertyPrimitive"
+                                                  #valueTransformationComponent>
+                    </sp-edit-value-transformation>
+
+                    <sp-edit-unit-transformation *ngIf="!isTimestampProperty && isEventPropertyPrimitive"
+                                                 [cachedProperty]="cachedProperty"
+                                                 [isTimestampProperty]="isTimestampProperty"
+                                                 [isNumericProperty]="isNumericProperty"
+                                                 [isPrimitiveProperty]="isEventPropertyPrimitive"
+                                                 #unitTransformationComponent>
+                    </sp-edit-unit-transformation>
+
+
+                </div>
+
+
+            </form>
+
+            <!--            <sp-edit-event-property-primitive-->
+            <!--                    *ngIf="isEventPropertyPrimitive"-->
+            <!--                    [isTimestampProperty]="isTimestampProperty"-->
+            <!--                    [cachedProperty]="cachedProperty"-->
+            <!--                    (isNumericDataType)="isNumericDataType($event)">-->
+            <!--            </sp-edit-event-property-primitive>-->
+            <!--            <sp-edit-event-property-list-->
+            <!--                    *ngIf="isEventPropertyList"-->
+            <!--                    [cachedProperty]="cachedProperty">-->
+            <!--            </sp-edit-event-property-list>-->
+        </div>
     </div>
-
-    <div class="form-group">
-      <mat-form-field class="doubleWidth" color="accent">
-        <textarea matInput name="description" placeholder="Description" id="description"
-          [(ngModel)]="cachedProperty.description" cols="20" rows="2"></textarea>
-      </mat-form-field>
-    </div>
-
-    <sp-edit-correction-value
-            *ngIf="isNumericProperty && !isTimestampProperty"
-            [cachedProperty]="cachedProperty"
-            (correctionValueChanged)="enableSaveBtn($event)">
-    </sp-edit-correction-value>
-
-    <div class="form-group">
-      <mat-form-field class="doubleWidth" color="accent">
-        <input matInput placeholder="Semantic Type" class="dmainProperty" name="domainproperty" id="domainproperty"
-               [(ngModel)]="cachedProperty.domainProperties[0]"
-               [matAutocomplete]="st"
-               [formControl]="domainPropertyControl">
-      <mat-autocomplete #st="matAutocomplete" [panelWidth]="'300px'">
-        <mat-option *ngFor="let semanticType of semanticTypes | async" [value]="semanticType" style="font-size: 10pt;">
-          {{semanticType}}
-        </mat-option>
-      </mat-autocomplete>
-      </mat-form-field>
-      <div *ngIf="!isEventPropertyNested">
-        <mat-checkbox name="timestampCheckbox"
-                      (change)="editTimestampDomainProperty($event.checked)"
-                      [checked]="isTimestampProperty"
-                      color="accent"
-                      data-cy="sp-mark-as-timestamp">
-          Mark as timestamp
-        </mat-checkbox>
-      </div>
-    </div>
-  </form>
-
-  <sp-edit-event-property-primitive
-          *ngIf="isEventPropertyPrimitive"
-          [isTimestampProperty]="isTimestampProperty"
-          [cachedProperty]="cachedProperty"
-          (isNumericDataType)="isNumericDataType($event)">
-  </sp-edit-event-property-primitive>
-  <sp-edit-event-property-list
-          *ngIf="isEventPropertyList"
-          [cachedProperty]="cachedProperty">
-  </sp-edit-event-property-list>
-
-</mat-dialog-content>
-
-<mat-dialog-actions>
-  <button mat-button mat-raised-button class="mat-basic" mat-dialog-close>Close</button>
-  <button mat-button mat-raised-button color="accent"
-          [disabled]="isSaveBtnEnabled"
-          (click)="save();
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <button mat-button mat-raised-button color="accent"
+                [disabled]="isSaveBtnEnabled"
+                (click)="save();
           isSaveBtnEnabled = false"
-          data-cy="sp-save-edit-property">
-    Save</button>
-</mat-dialog-actions>
+                style="margin-right: 10px;"
+                data-cy="sp-save-edit-property">
+            Save
+        </button>
+        <button mat-button mat-raised-button class="mat-basic" (click)="dialogRef.close()">Close</button>
+    </div>
+</div>
diff --git a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.scss b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.scss
index 03fa4b4..85d8c6a 100644
--- a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.scss
+++ b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.scss
@@ -16,6 +16,8 @@
  *
  */
 
+@import '../../../../scss/sp/sp-dialog.scss';
+
 .doubleWidth {
     width: 370px !important;
 }
@@ -24,3 +26,7 @@
     justify-content: flex-end;
 }
 
+.full-width {
+    width: 100%;
+}
+
diff --git a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
index d7c7189..d3a3dc9 100644
--- a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
+++ b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
@@ -16,20 +16,21 @@
  *
  */
 
-import { Component, EventEmitter, Inject, OnInit, Output } from '@angular/core';
-import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 import {
-    EventPropertyList,
-    EventPropertyNested,
-    EventPropertyPrimitive,
-    EventPropertyUnion,
-    SemanticTypesService
+  EventPropertyList,
+  EventPropertyNested,
+  EventPropertyPrimitive,
+  EventPropertyUnion,
+  SemanticTypesService
 } from '@streampipes/platform-services';
 import { SemanticTypeUtilsService } from '../../../core-services/semantic-type/semantic-type-utils.service';
 import { DataTypesService } from '../../services/data-type.service';
-import { Observable } from 'rxjs';
-import { debounceTime, distinctUntilChanged, startWith, switchMap } from 'rxjs/operators';
+import { DialogRef } from '@streampipes/shared-ui';
+import { EditSchemaTransformationComponent } from './components/edit-schema-transformation/edit-schema-transformation.component';
+import { EditValueTransformationComponent } from './components/edit-value-transformation/edit-value-transformation.component';
+import { EditUnitTransformationComponent } from './components/edit-unit-transformation/edit-unit-transformation.component';
 
 @Component({
   selector: 'sp-edit-event-property',
@@ -38,13 +39,16 @@
 })
 export class EditEventPropertyComponent implements OnInit {
 
-  soTimestamp = 'http://schema.org/DateTime';
+  @Input() property: EventPropertyUnion;
+  @Input() isEditable: boolean;
 
   @Output() propertyChange = new EventEmitter<EventPropertyUnion>();
 
+  schemaTransformationComponent: EditSchemaTransformationComponent;
+  valueTransformationComponent: EditValueTransformationComponent;
+  unitTransformationComponent: EditUnitTransformationComponent;
+
   cachedProperty: any;
-  property: any;
-  isEditable: boolean;
 
   isTimestampProperty = false;
   isEventPropertyPrimitive: boolean;
@@ -53,15 +57,11 @@
   isNumericProperty: boolean;
   isSaveBtnEnabled: boolean;
 
-  semanticTypes: Observable<string[]>;
-
   private propertyForm: FormGroup;
-  domainPropertyControl = new FormControl();
 
   private runtimeDataTypes;
 
-  constructor(@Inject(MAT_DIALOG_DATA) public data: any,
-              private dialogRef: MatDialogRef<EditEventPropertyComponent>,
+  constructor(public dialogRef: DialogRef<EditEventPropertyComponent>,
               private formBuilder: FormBuilder,
               private dataTypeService: DataTypesService,
               private semanticTypeUtilsService: SemanticTypeUtilsService,
@@ -69,8 +69,6 @@
   }
 
   ngOnInit(): void {
-    this.property = this.data.property;
-    this.isEditable = this.data.isEditable;
     this.cachedProperty = this.copyEp(this.property);
     this.runtimeDataTypes = this.dataTypeService.getDataTypes();
     this.isTimestampProperty = this.semanticTypeUtilsService.isTimestamp(this.cachedProperty);
@@ -80,15 +78,7 @@
     this.isNumericProperty = this.semanticTypeUtilsService.isNumeric(this.cachedProperty) ||
       this.dataTypeService.isNumeric(this.cachedProperty.runtimeType);
     this.createForm();
-    this.semanticTypes = this.domainPropertyControl.valueChanges
-      .pipe(
-        startWith(''),
-        debounceTime(400),
-        distinctUntilChanged(),
-        switchMap(val => {
-          return val ? this.semanticTypesService.getSemanticTypes(val) : [];
-        })
-      );
+
   }
 
   copyEp(ep: EventPropertyUnion) {
@@ -131,19 +121,6 @@
     return (this.property.elementId.startsWith('http://eventProperty.de/staticValue/'));
   }
 
-  editTimestampDomainProperty(checked: boolean) {
-    if (checked) {
-      this.isTimestampProperty = true;
-      this.cachedProperty.domainProperties = [this.soTimestamp];
-      this.cachedProperty.propertyScope = 'HEADER_PROPERTY';
-      this.cachedProperty.runtimeType = 'http://www.w3.org/2001/XMLSchema#long';
-    } else {
-      this.cachedProperty.domainProperties = [];
-      this.cachedProperty.propertyScope = 'MEASUREMENT_PROPERTY';
-      this.isTimestampProperty = false;
-    }
-  }
-
   save(): void {
     this.property.label = this.cachedProperty.label;
     this.property.description = this.cachedProperty.description;
@@ -176,7 +153,7 @@
       (this.property as any).correctionValue = (this.cachedProperty as any).correctionValue;
       (this.property as any).operator = (this.cachedProperty as any).operator;
     }
-    this.dialogRef.close({ data: this.property });
+    this.dialogRef.close({data: this.property});
   }
 
   enableSaveBtn($event: boolean) {
@@ -191,4 +168,24 @@
     }
     this.isNumericProperty = $event;
   }
+
+  handleDataTypeChange(changed: boolean) {
+    this.isNumericProperty = this.dataTypeService.isNumeric(this.cachedProperty.runtimeType);
+  }
+
+  handleTimestampChange(isTimestamp: boolean) {
+    this.isTimestampProperty = isTimestamp;
+  }
+
+  @ViewChild('schemaTransformationComponent') set schemaTransformation(comp: EditSchemaTransformationComponent) {
+    this.schemaTransformationComponent = comp;
+  }
+
+  @ViewChild('unitTransformationComponent') set unitTransformation(comp: EditUnitTransformationComponent) {
+    this.unitTransformationComponent = comp;
+  }
+
+  @ViewChild('valueTransformationComponent') set valueTransformation(comp: EditValueTransformationComponent) {
+    this.valueTransformationComponent = comp;
+  }
 }
diff --git a/ui/src/app/connect/filter/adapter-filter.pipe.ts b/ui/src/app/connect/filter/adapter-filter.pipe.ts
new file mode 100644
index 0000000..8691a93
--- /dev/null
+++ b/ui/src/app/connect/filter/adapter-filter.pipe.ts
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable, Pipe, PipeTransform } from '@angular/core';
+import { AdapterDescriptionUnion } from '@streampipes/platform-services';
+import { AdapterFilterSettingsModel } from '../model/adapter-filter-settings.model';
+import { ConnectService } from '../services/connect.service';
+
+@Pipe({ name: 'adapterFilter' })
+@Injectable({ providedIn: 'root' })
+export class AdapterFilterPipe implements PipeTransform {
+
+  constructor(private connectService: ConnectService) {
+  }
+
+  transform(adapterDescriptions: AdapterDescriptionUnion[],
+            activeFilters: AdapterFilterSettingsModel): AdapterDescriptionUnion[] {
+    if (!activeFilters) {
+      return adapterDescriptions;
+    } else {
+      return adapterDescriptions.filter(a => this.meetsFilterCondition(a, activeFilters));
+    }
+  }
+
+  private meetsFilterCondition(adapterDescription: AdapterDescriptionUnion,
+                               activeFilters: AdapterFilterSettingsModel): boolean {
+    return this.meetsFilterTypeCondition(adapterDescription, activeFilters.selectedType) &&
+      this.meetsFilterCategoryCondition(adapterDescription, activeFilters.selectedCategory) &&
+      this.meetsFilterTextCondition(adapterDescription, activeFilters.textFilter);
+  }
+
+  private meetsFilterTypeCondition(adapterDescription: AdapterDescriptionUnion,
+                                   selectedType: string): boolean {
+    if (selectedType === 'All types') {
+      return true;
+    } else if (selectedType === 'Data Set') {
+      return this.connectService.isDataSetDescription(adapterDescription);
+    } else if (selectedType === 'Data Stream') {
+      return !this.connectService.isDataSetDescription(adapterDescription);
+    }
+  }
+
+  private meetsFilterCategoryCondition(adapterDescription: AdapterDescriptionUnion,
+                                       selectedCategory: string): boolean {
+    if (selectedCategory === 'All') {
+      return true;
+    } else {
+      return adapterDescription.category.indexOf(selectedCategory) !== -1;
+    }
+  }
+
+  private meetsFilterTextCondition(adapterDescription: AdapterDescriptionUnion,
+                                   filterTerm: string): boolean {
+    if (filterTerm === undefined || filterTerm === '') {
+      return true;
+    } else {
+      if (adapterDescription.name == null) {
+        return true;
+      } else {
+        adapterDescription.name.replace(' ', '_');
+        return adapterDescription.name.toLowerCase().includes(filterTerm.toLowerCase()) ||
+          adapterDescription.description.toLowerCase().includes(filterTerm.toLowerCase());
+      }
+    }
+  }
+}
diff --git a/ui/src/app/connect/filter/filter.pipe.ts b/ui/src/app/connect/filter/filter.pipe.ts
deleted file mode 100644
index b7f663f..0000000
--- a/ui/src/app/connect/filter/filter.pipe.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Pipe, PipeTransform } from '@angular/core';
-import { AdapterDescriptionUnion } from '@streampipes/platform-services';
-
-@Pipe({
-    name: 'filter'
-})
-
-export class FilterPipe implements PipeTransform {
-
-    transform(adapterDescriptions: AdapterDescriptionUnion[], filterTerm?: any): any {
-        // check if search filterTerm is undefined
-        if (filterTerm === undefined || !adapterDescriptions) { return adapterDescriptions; }
-        return adapterDescriptions.filter(adapterDescription => {
-            if (adapterDescription.name == null) {
-                return true;
-            } else {
-                adapterDescription.name.replace(' ', '_');
-                return adapterDescription.name.toLowerCase().includes(filterTerm.toLowerCase()) ||
-                    adapterDescription.description.toLowerCase().includes(filterTerm.toLowerCase());
-            }
-        });
-    }
-}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/filter/json-pretty-print.pipe.ts
similarity index 70%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/connect/filter/json-pretty-print.pipe.ts
index 58ba04b..5383916 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/filter/json-pretty-print.pipe.ts
@@ -16,3 +16,18 @@
  *
  */
 
+import { Injectable, Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+  name: 'jsonpretty'
+})
+@Injectable({providedIn: 'root'})
+export class JsonPrettyPrintPipe implements PipeTransform {
+
+  transform(json) {
+    return JSON.stringify(json, undefined, 4)
+      .replace(/ /g, '&nbsp;')
+      .replace(/\n/g, '<br/>');
+  }
+
+}
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/connect/model/adapter-filter-settings.model.ts
similarity index 86%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/connect/model/adapter-filter-settings.model.ts
index 58ba04b..3b30586 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/connect/model/adapter-filter-settings.model.ts
@@ -16,3 +16,8 @@
  *
  */
 
+export interface AdapterFilterSettingsModel {
+  textFilter: string;
+  selectedType: string;
+  selectedCategory: string;
+}
diff --git a/ui/src/app/connect/services/adapter-template.service.ts b/ui/src/app/connect/services/adapter-template.service.ts
new file mode 100644
index 0000000..d7c0815
--- /dev/null
+++ b/ui/src/app/connect/services/adapter-template.service.ts
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { SpAdapterTemplateDialogComponent } from '../dialog/adapter-template/adapter-template-dialog.component';
+import { DialogService, PanelType } from '@streampipes/shared-ui';
+import { AdapterDescriptionUnion } from '@streampipes/platform-services';
+import { StaticPropertyUnion } from '../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+
+@Injectable({providedIn: 'root'})
+export class AdapterTemplateService {
+
+  constructor(private dialogService: DialogService) {
+
+  }
+
+  getDialog(configs: StaticPropertyUnion[],
+            appId: string) {
+    return this.dialogService.open(SpAdapterTemplateDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Create configuration template',
+      width: '50vw',
+      data: {
+        'configs': configs,
+        'appId': appId
+      }
+    });
+  }
+
+}
diff --git a/ui/src/app/connect/services/connect.service.ts b/ui/src/app/connect/services/connect.service.ts
index 1e4b73d..740cc43 100644
--- a/ui/src/app/connect/services/connect.service.ts
+++ b/ui/src/app/connect/services/connect.service.ts
@@ -25,6 +25,7 @@
   SpecificAdapterSetDescription,
   SpecificAdapterStreamDescription
 } from '@streampipes/platform-services';
+import { AdapterDescriptionUnion } from '../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
 
 @Injectable()
 export class ConnectService {
@@ -67,5 +68,25 @@
     }
   }
 
+  cloneAdapterDescription(toClone: AdapterDescriptionUnion): AdapterDescriptionUnion {
+    let result: AdapterDescriptionUnion;
+
+    if (this.isGenericDescription(toClone)) {
+      if (toClone instanceof GenericAdapterStreamDescription) {
+        result = GenericAdapterStreamDescription.fromData(toClone, new GenericAdapterStreamDescription());
+      } else if (toClone instanceof GenericAdapterSetDescription) {
+        result = GenericAdapterSetDescription.fromData(toClone, new GenericAdapterSetDescription());
+      }
+    } else {
+      if (toClone instanceof SpecificAdapterStreamDescription) {
+        result = SpecificAdapterStreamDescription.fromData(toClone, new SpecificAdapterStreamDescription());
+      } else if (toClone instanceof SpecificAdapterSetDescription) {
+        result = SpecificAdapterSetDescription.fromData(toClone, new SpecificAdapterSetDescription());
+      }
+    }
+
+    return result;
+  }
+
 
 }
diff --git a/ui/src/app/connect/services/rest.service.ts b/ui/src/app/connect/services/rest.service.ts
index 5d33cdc..17459d5 100644
--- a/ui/src/app/connect/services/rest.service.ts
+++ b/ui/src/app/connect/services/rest.service.ts
@@ -23,16 +23,20 @@
 import { from, Observable } from 'rxjs';
 import { map } from 'rxjs/operators';
 import { UnitDescription } from '../model/UnitDescription';
-import { AdapterDescription, FormatDescription, GuessSchema, Message, SpDataStream, PlatformServicesCommons } from '@streampipes/platform-services';
+import {
+  AdapterDescription, FormatDescription, GuessSchema, Message, SpDataStream, PlatformServicesCommons,
+  AdapterEventPreview,
+  GuessTypeInfo
+} from '@streampipes/platform-services';
 import { AuthService } from '../../services/auth.service';
 
 @Injectable()
 export class RestService {
 
   constructor(
-      private http: HttpClient,
-      private platformServicesCommons: PlatformServicesCommons,
-      private authService: AuthService) {
+    private http: HttpClient,
+    private platformServicesCommons: PlatformServicesCommons,
+    private authService: AuthService) {
   }
 
   get connectPath() {
@@ -66,7 +70,11 @@
       .pipe(map(response => {
         return GuessSchema.fromData(response as GuessSchema);
       }));
+  }
 
+  getAdapterEventPreview(adapterEventPreview: AdapterEventPreview): Observable<Record<string, GuessTypeInfo>> {
+    return this.http.post(`${this.connectPath}/master/guess/schema/preview`, adapterEventPreview)
+      .pipe(map(response => response as Record<string, GuessTypeInfo>));
   }
 
   getSourceDetails(sourceElementId): Observable<SpDataStream> {
@@ -78,7 +86,7 @@
 
   getRuntimeInfo(sourceDescription): Observable<any> {
     return this.http.post(`${this.platformServicesCommons.apiBasePath}/pipeline-element/runtime`, sourceDescription, {
-      headers: { ignoreLoadingBar: '' }
+      headers: {ignoreLoadingBar: ''}
     });
   }
 
diff --git a/ui/src/app/connect/services/transformation-rule.service.ts b/ui/src/app/connect/services/transformation-rule.service.ts
index 8781956..4786696 100644
--- a/ui/src/app/connect/services/transformation-rule.service.ts
+++ b/ui/src/app/connect/services/transformation-rule.service.ts
@@ -30,6 +30,7 @@
   EventSchema,
   MoveRuleDescription,
   RenameRuleDescription,
+  ChangeDatatypeTransformationRuleDescription,
   TimestampTranfsformationRuleDescription,
   TransformationRuleDescriptionUnion,
   UnitTransformRuleDescription
@@ -82,33 +83,16 @@
       }
 
       // Scale
-      transformationRuleDescription = transformationRuleDescription.concat(this.getCorrectionValueRules(
-        this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema));
+      transformationRuleDescription = transformationRuleDescription
+        .concat(this.getCorrectionValueRules(this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema))
+        .concat(this.getRenameRules(this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema))
+        .concat(this.getCreateNestedRules(this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema))
+        .concat(this.getMoveRules(this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema))
+        .concat(this.getDeleteRules(this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema))
+        .concat(this.getUnitTransformRules(this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema))
+        .concat(this.getTimestampTransformRules(this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema))
+        .concat(this.getDatatypeTransformRules(this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema));
 
-      // Rename
-      transformationRuleDescription = transformationRuleDescription.concat(this.getRenameRules(
-        this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema));
-
-
-      // Create Nested
-      transformationRuleDescription = transformationRuleDescription.concat(this.getCreateNestedRules(
-        this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema));
-
-      // Move
-      transformationRuleDescription = transformationRuleDescription.concat(this.getMoveRules(
-        this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema));
-
-      // Delete
-      transformationRuleDescription = transformationRuleDescription.concat(this.getDeleteRules(
-        this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema));
-
-      // Unit
-      transformationRuleDescription = transformationRuleDescription.concat(this.getUnitTransformRules(
-        this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema));
-
-      // Timestmap
-      transformationRuleDescription = transformationRuleDescription.concat(this.getTimestampTransformRules(
-        this.newEventSchema.eventProperties, this.oldEventSchema, this.newEventSchema));
 
       return transformationRuleDescription;
     }
@@ -454,6 +438,40 @@
     return property.domainProperties.some(dp => dp === 'http://schema.org/DateTime');
   }
 
+  private getDatatypeTransformRules(eventProperties: EventPropertyUnion[],
+                                    oldEventSchema: EventSchema,
+                                    newEventSchema: EventSchema): ChangeDatatypeTransformationRuleDescription[] {
+
+    let result: ChangeDatatypeTransformationRuleDescription[] = [];
+
+    eventProperties.forEach(ep => {
+      if (ep instanceof EventPropertyPrimitive) {
+        const eventPropertyPrimitive = ep as EventPropertyPrimitive;
+        const newRuntimeType = ep.runtimeType;
+        const keyNew = this.getCompleteRuntimeNameKey(newEventSchema.eventProperties, eventPropertyPrimitive.elementId);
+        const oldProperty = this.getEventProperty(oldEventSchema.eventProperties, ep.elementId);
+        if (oldProperty) {
+          const oldRuntimeType = (oldProperty as EventPropertyPrimitive).runtimeType;
+          if (newRuntimeType !== oldRuntimeType) {
+            const rule: ChangeDatatypeTransformationRuleDescription = new ChangeDatatypeTransformationRuleDescription();
+            rule['@class'] = 'org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription';
+            rule.runtimeKey = keyNew;
+            rule.originalDatatypeXsd = oldRuntimeType;
+            rule.targetDatatypeXsd = newRuntimeType;
+
+            result.push(rule);
+          }
+        }
+
+      } else if (ep instanceof EventPropertyNested) {
+        const nestedResults = this.getDatatypeTransformRules((ep as EventPropertyNested).eventProperties, oldEventSchema, newEventSchema);
+        result = result.concat(nestedResults);
+      }
+    });
+
+    return result;
+  }
+
   private getCorrectionValueRules(eventProperties: EventPropertyUnion[],
                                   oldEventSchema: EventSchema,
                                   newEventSchema: EventSchema) {
diff --git a/ui/src/app/core-model/base/UserErrorMessage.ts b/ui/src/app/core-model/base/UserErrorMessage.ts
index 85322e0..2fc7f5c 100644
--- a/ui/src/app/core-model/base/UserErrorMessage.ts
+++ b/ui/src/app/core-model/base/UserErrorMessage.ts
@@ -19,9 +19,11 @@
 export class UserErrorMessage {
   public title: string;
   public content: string;
+  public level: string;
 
-  constructor(title: string, content: string) {
+  constructor(title: string, content: string, level = 'error') {
     this.title = title;
     this.content = content;
+    this.level = level;
   }
 }
diff --git a/ui/src/app/core-services/template/PipelineInvocationBuilder.ts b/ui/src/app/core-services/template/PipelineInvocationBuilder.ts
index 57c094a..cec4cf0 100644
--- a/ui/src/app/core-services/template/PipelineInvocationBuilder.ts
+++ b/ui/src/app/core-services/template/PipelineInvocationBuilder.ts
@@ -41,7 +41,7 @@
 
   public setFreeTextStaticProperty(name: string, value: string) {
     this.pipelineTemplateInvocation.staticProperties.forEach(property => {
-      if (property instanceof FreeTextStaticProperty && 'domId2' + name === property.internalName) {
+      if (property instanceof FreeTextStaticProperty && 'jsplumb_domId2' + name === property.internalName) {
         property.value = value;
       }
     });
@@ -51,7 +51,7 @@
 
   public setMappingPropertyUnary(name: string, value: string) {
     this.pipelineTemplateInvocation.staticProperties.forEach(property => {
-      if (property instanceof MappingPropertyUnary && 'domId2' + name === property.internalName) {
+      if (property instanceof MappingPropertyUnary && 'jsplumb_domId2' + name === property.internalName) {
         property.selectedProperty = value;
       }
     });
diff --git a/ui/src/app/core-ui/core-ui.module.ts b/ui/src/app/core-ui/core-ui.module.ts
index 22c3f48..89f0163 100644
--- a/ui/src/app/core-ui/core-ui.module.ts
+++ b/ui/src/app/core-ui/core-ui.module.ts
@@ -82,6 +82,10 @@
 import { PlatformServicesModule } from '@streampipes/platform-services';
 import { ImageBarPreviewComponent } from './image/components/image-bar/image-bar-preview/image-bar-preview.component';
 import { SharedUiModule } from '@streampipes/shared-ui';
+import { PipelineElementTemplateConfigComponent } from './pipeline-element-template-config/pipeline-element-template-config.component';
+import { PipelineElementTemplatePipe } from './pipeline-element-template-config/pipeline-element-template.pipe';
+import { DataDownloadDialogComponent } from './data-download-dialog/data-download-dialog.component';
+import { OwlDateTimeModule, OwlNativeDateTimeModule } from '@danielmoncada/angular-datetime-picker';
 
 @NgModule({
   imports: [
@@ -104,6 +108,8 @@
     MatSlideToggleModule,
     MatChipsModule,
     MatTreeModule,
+    OwlDateTimeModule,
+    OwlNativeDateTimeModule,
     PlatformServicesModule,
     PortalModule,
     SharedUiModule,
@@ -113,6 +119,7 @@
   ],
   declarations: [
     ConfigureLabelsComponent,
+    DataDownloadDialogComponent,
     DisplayRecommendedPipe,
     ImageBarPreviewComponent,
     ImageComponent,
@@ -123,6 +130,8 @@
     ImageAnnotationsComponent,
     ImageViewerComponent,
     ObjectPermissionDialogComponent,
+    PipelineElementTemplateConfigComponent,
+    PipelineElementTemplatePipe,
     SplitSectionComponent,
     StaticAnyInput,
     StaticPropertyComponent,
@@ -159,8 +168,10 @@
   ],
   exports: [
     ConfigureLabelsComponent,
+    DataDownloadDialogComponent,
     ImageComponent,
     ImageLabelingComponent,
+    PipelineElementTemplateConfigComponent,
     SelectLabelComponent,
     StaticAnyInput,
     StaticPropertyComponent,
diff --git a/ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.html b/ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.html
new file mode 100644
index 0000000..4c8675a
--- /dev/null
+++ b/ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.html
@@ -0,0 +1,114 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100">
+            <mat-horizontal-stepper #stepper>
+                <mat-step>
+                    <ng-template matStepLabel>Select Data</ng-template>
+                    <div class="mt-10">
+                        <mat-radio-group class="sp-radio-group" [(ngModel)]="selectedData">
+                            <mat-radio-button value="visible" class="sp-radio-button" *ngIf="dataConfig">
+                                Currently configured query
+                            </mat-radio-button>
+                            <div fxLayout="column" fxLayoutAlign="start start" class="ml-35 mb-10" *ngIf="selectedData === 'visible' && dataConfig && dataConfig.sourceConfigs.length > 1">
+                                <h5>Select source (only one source can be exported in a single file)</h5>
+                                <mat-radio-group class="sp-radio-group" [(ngModel)]="selectedQueryIndex" fxLayout="column">
+                                    <mat-radio-button [value]="i" *ngFor="let sourceConfig of dataConfig.sourceConfigs; let i = index" class="p-5">
+                                        {{sourceConfig.measureName}}
+                                    </mat-radio-button>
+                                </mat-radio-group>
+                            </div>
+                            <mat-radio-button value="all" class="sp-radio-button">
+                                All data in database
+                            </mat-radio-button>
+                            <mat-radio-button value="customInterval" class="sp-radio-button">
+                                All data in custom time interval
+                            </mat-radio-button>
+                        </mat-radio-group>
+                        <div fxLayout="row" fxLayoutAlign="start center" class="ml-35">
+                            <mat-form-field class="form-field-date">
+                                <input matInput [owlDateTime]="dt1" [owlDateTimeTrigger]="dt1"
+                                       [(ngModel)]="dateRange" [selectMode]="'range'"
+                                       [disabled]="selectedData !== 'customInterval'">
+                                <mat-icon matSuffix [owlDateTimeTrigger]="dt1"
+                                          *ngIf="selectedData === 'customInterval'">event
+                                </mat-icon>
+                                <mat-icon matSuffix class="event-color" *ngIf="selectedData !== 'customInterval'">
+                                    event
+                                </mat-icon>
+                                <owl-date-time #dt1></owl-date-time>
+                            </mat-form-field>
+                        </div>
+                    </div>
+                </mat-step>
+
+
+                <mat-step>
+                    <ng-template matStepLabel>Select Format</ng-template>
+                    <div>
+                        <h5>Download Format</h5>
+                        <mat-radio-group class="sp-radio-group" [(ngModel)]="downloadFormat">
+                            <mat-radio-button value="json" class="sp-radio-button">
+                                JSON
+                            </mat-radio-button>
+                            <mat-radio-button value="csv" class="sp-radio-button">
+                                CSV
+                            </mat-radio-button>
+                        </mat-radio-group>
+                    </div>
+                    <div *ngIf="downloadFormat === 'csv'" class="mt-10">
+                        <h5>Delimiter</h5>
+                        <mat-radio-group [(ngModel)]="delimiter" class="sp-radio-group">
+                            <mat-radio-button value="comma" class="sp-radio-button">&nbsp;,</mat-radio-button>
+                            <mat-radio-button value="semicolon" class="sp-radio-button">&nbsp;;</mat-radio-button>
+                        </mat-radio-group>
+                    </div>
+                </mat-step>
+
+
+                <mat-step>
+                    <ng-template matStepLabel>Download</ng-template>
+                    <div fxFlex="100" fxLayout="column" fxLayoutAlign="center center" *ngIf="!downloadFinish" class="mt-35">
+                        <mat-spinner [diameter]="30" color="accent"></mat-spinner>
+                        <label *ngIf="downloadedMBs !== undefined">{{downloadedMBs | number : '1.0-2' }} Mb</label>
+                        <button mat-button warn color="warn" (click)="cancelDownload()">Cancel</button>
+                    </div>
+                    <div fxLayout="column" fxLayoutAlign="space-around center" *ngIf="downloadFinish">
+                        <mat-icon class="icon-check">check</mat-icon>
+                        <h5>Download successful</h5>
+                    </div>
+                </mat-step>
+            </mat-horizontal-stepper>
+
+        </div>
+    </div>
+
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions actions-align-right">
+        <button mat-button mat-raised-button class="mat-basic" style="margin-right: 10px;" (click)="exitDialog()">Close</button>
+        <button mat-button mat-raised-button class="mat-basic" style="margin-right: 10px;" *ngIf="stepper.selectedIndex == 1" (click)="previousStep()">Previous</button>
+        <button mat-button mat-raised-button *ngIf="stepper.selectedIndex < 1" color="accent" (click)="nextStep()">
+            Next
+        </button>
+        <button mat-button mat-raised-button *ngIf="stepper.selectedIndex == 1" color="accent" (click)="downloadData()">
+            Download
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.css b/ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.scss
similarity index 93%
rename from ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.css
rename to ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.scss
index 0ff348e..1a799af 100644
--- a/ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.css
+++ b/ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.scss
@@ -16,12 +16,14 @@
  *
  */
 
-example-radio-group {
+@import 'src/scss/sp/sp-dialog';
+
+.sp-radio-group {
     display: flex;
     flex-direction: column;
     margin: 15px 0;
 }
-.example-radio-button {
+.sp-radio-button {
     margin: 5px;
     width: 100%;
 }
@@ -59,6 +61,10 @@
     margin-left: 35px;
 }
 
+.mt-35 {
+    margin-top: 35px;
+}
+
 .form-field-date {
     top: -10px;
     width: 270px;
diff --git a/ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.ts b/ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.ts
new file mode 100644
index 0000000..b68aadd
--- /dev/null
+++ b/ui/src/app/core-ui/data-download-dialog/data-download-dialog.component.ts
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { HttpEventType } from '@angular/common/http';
+import { Component, Input, OnInit, ViewChild } from '@angular/core';
+import { MatStepper } from '@angular/material/stepper';
+import {
+  DataExplorerDataConfig,
+  DatalakeQueryParameters,
+  DatalakeRestService,
+  DataViewQueryGeneratorService,
+  DateRange
+} from '@streampipes/platform-services';
+import { DialogRef } from '@streampipes/shared-ui';
+
+
+@Component({
+  selector: 'sp-data-download-dialog',
+  templateUrl: 'data-download-dialog.component.html',
+  styleUrls: ['./data-download-dialog.component.scss']
+})
+// tslint:disable-next-line:component-class-suffix
+export class DataDownloadDialogComponent implements OnInit {
+
+  /**
+   * Provide either measureName without additional configuration
+   * or dataConfig to allow selection of multiple sources
+   */
+  @Input() measureName: string;
+  @Input() dataConfig: DataExplorerDataConfig;
+
+  @Input() date: DateRange;
+
+  downloadFormat = 'csv';
+  delimiter = 'comma';
+  selectedData = 'visible';
+  downloadFinish = false;
+  downloadedMBs: number = undefined;
+  selectedQueryIndex = 0;
+
+  @ViewChild('stepper', {static: true}) stepper: MatStepper;
+
+  downloadHttpRequestSubscribtion;
+
+  dateRange: Date [] = []; // [0] start, [1] end
+
+
+  constructor(public dialogRef: DialogRef<DataDownloadDialogComponent>,
+              public datalakeRestService: DatalakeRestService,
+              private dataViewQueryService: DataViewQueryGeneratorService) {
+  }
+
+  ngOnInit() {
+    if (!this.date) {
+      const endDate = new Date();
+      endDate.setDate(endDate.getDate() - 5);
+      this.date = {startDate: new Date(), endDate};
+    }
+    this.dateRange[0] = this.date.startDate;
+    this.dateRange[1] = this.date.endDate;
+
+    if (!this.dataConfig) {
+      this.selectedData = 'all';
+    }
+  }
+
+  downloadData() {
+    const index = !this.dataConfig ?
+      this.measureName : this.dataConfig.sourceConfigs[this.selectedQueryIndex].measureName;
+    this.nextStep();
+    const startTime = this.date.startDate.getTime();
+    const endTime = this.date.endDate.getTime();
+    const startDateString = this.getDateString(this.date.startDate);
+    const endDateString = this.getDateString(this.date.endDate);
+    switch (this.selectedData) {
+      case 'all':
+        this.performRequest(this.datalakeRestService.downloadRawData(
+          index,
+          this.downloadFormat,
+          this.delimiter), '', '');
+        break;
+      case 'customInterval':
+        this.performRequest(this.datalakeRestService.downloadRawData(
+            index,
+            this.downloadFormat,
+            this.delimiter,
+            startTime,
+            endTime), startDateString,
+          endDateString);
+        break;
+      case 'visible':
+        this.performRequest(
+          this.datalakeRestService
+            .downloadQueriedData(
+              index,
+              this.downloadFormat,
+              this.delimiter,
+              this.generateQueryRequest(startTime, endTime)
+            ),
+          startDateString,
+          endDateString
+        );
+
+    }
+  }
+
+  generateQueryRequest(startTime: number,
+                       endTime: number): DatalakeQueryParameters {
+    return this.dataViewQueryService
+      .generateQuery(startTime, endTime, this.dataConfig.sourceConfigs[this.selectedQueryIndex]);
+  }
+
+  performRequest(request, startDate, endDate) {
+    this.downloadHttpRequestSubscribtion = request.subscribe(event => {
+      // progress
+      if (event.type === HttpEventType.DownloadProgress) {
+        this.downloadedMBs = event.loaded / 1024 / 1014;
+      }
+
+      // finished
+      if (event.type === HttpEventType.Response) {
+        this.createFile(event.body, this.downloadFormat, this.measureName, startDate, endDate);
+        this.downloadFinish = true;
+      }
+    });
+  }
+
+  convertData(data, format, xAxesKey, yAxesKeys) {
+    const indexXKey = data.headers.findIndex(headerName => headerName === xAxesKey);
+    const indicesYKeys = [];
+    yAxesKeys.forEach(key => {
+      indicesYKeys.push(data.headers.findIndex(headerName => headerName === key));
+    });
+
+    if (format === 'json') {
+      const resultJson = [];
+
+
+      data.rows.forEach(row => {
+        const tmp = {'time': new Date(row[indexXKey]).getTime()};
+        indicesYKeys.forEach(index => {
+          if (row[index] !== undefined) {
+            tmp[data.headers[index]] = row[index];
+          }
+        });
+        resultJson.push(tmp);
+      });
+
+      return JSON.stringify(resultJson);
+    } else {
+      // CSV
+      let resultCsv = '';
+
+      // header
+      resultCsv += xAxesKey;
+      yAxesKeys.forEach(key => {
+        resultCsv += ';';
+        resultCsv += key;
+      });
+
+
+      // content
+      data.rows.forEach(row => {
+        resultCsv += '\n';
+        resultCsv += new Date(row[indexXKey]).getTime();
+        indicesYKeys.forEach(index => {
+          resultCsv += ';';
+          if (row[index] !== undefined) {
+            resultCsv += row[index];
+          }
+        });
+      });
+
+      return resultCsv;
+    }
+  }
+
+  createFile(data, format, fileName, startDate, endDate) {
+    const a = document.createElement('a');
+    document.body.appendChild(a);
+    a.style.display = 'display: none';
+
+    let name = 'sp_' + startDate + '_' + fileName + '.' + this.downloadFormat;
+    name = name.replace('__', '_');
+
+    const url = window.URL.createObjectURL(new Blob([String(data)], {type: 'data:text/' + format + ';charset=utf-8'}));
+    a.href = url;
+    a.download = name;
+    a.click();
+    window.URL.revokeObjectURL(url);
+  }
+
+  cancelDownload() {
+    try {
+      this.downloadHttpRequestSubscribtion.unsubscribe();
+    } finally {
+      this.exitDialog();
+    }
+  }
+
+
+  exitDialog(): void {
+    this.dialogRef.close();
+  }
+
+  nextStep() {
+    this.stepper.next();
+  }
+
+  previousStep() {
+    this.stepper.previous();
+  }
+
+  getDateString(date: Date): string {
+    return date.toLocaleDateString() + 'T' + date.toLocaleTimeString().replace(':', '.')
+      .replace(':', '.');
+  }
+
+}
diff --git a/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.html b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.html
new file mode 100644
index 0000000..712119d
--- /dev/null
+++ b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.html
@@ -0,0 +1,73 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="p-15">
+    <div fxFlex="100" fxLayout="column">
+        <h4>Basics</h4>
+        <mat-form-field fxFlex color="accent">
+            <mat-label>Template name</mat-label>
+            <input [(ngModel)]="template.templateName" matInput name="templateName" class="sp" required/>
+        </mat-form-field>
+        <mat-form-field fxFlex color="accent">
+            <mat-label>Template description</mat-label>
+            <input [(ngModel)]="template.templateDescription" matInput name="templateDescription" class="sp"
+                   required/>
+        </mat-form-field>
+        <!--        <mat-checkbox class="sp" color="accent">Make available as pipeline element</mat-checkbox>-->
+        <mat-divider class="divider"></mat-divider>
+        <h4>Configuration</h4>
+        <mat-hint style="margin-bottom: 10px;">(dynamic options cannot be saved and are hidden)</mat-hint>
+        <div fxLayout="column" *ngFor="let config of staticProperties | pipelineElementTemplatePipe"
+             class="static-property-panel static-property-panel-border">
+            <div fxLayout="row">
+                <div fxFlex="50">
+                    {{config.label}}
+                </div>
+                <div fxFlex="50">
+                    <div fxLayout="column">
+                        <mat-checkbox [checked]="templateConfigs.has(config.internalName)"
+                                      (change)="handleSelection(config)" name="store" class="sp" color="accent">Store
+                            as template
+                        </mat-checkbox>
+                        <!--                        <mat-checkbox *ngIf="templateConfigs.has(config.internalName)"-->
+                        <!--                                      (click)="toggleViewPermission(config)" name="displayed"-->
+                        <!--                                      class="sp" color="primary">Users can view-->
+                        <!--                        </mat-checkbox>-->
+                        <!--                        <mat-checkbox *ngIf="templateConfigs.has(config.internalName)"-->
+                        <!--                                      (click)="toggleEditPermission(config)" name="editable"-->
+                        <!--                                      class="sp" color="primary">Users can modify-->
+                        <!--                        </mat-checkbox>-->
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        <mat-divider class="divider"></mat-divider>
+        <h4>Existing templates</h4>
+        <div fxLayout="column" *ngFor="let template of existingTemplates" class="static-property-panel static-property-panel-border">
+            <div fxFlex="100" fxLayout="row">
+                <div fxFlex fxLayoutAlign="start center">{{template.templateName}}</div>
+                <div fxLayoutAlign="end center">
+                    <button mat-icon-button color="accent" (click)="deleteTemplate(template._id)"><mat-icon>delete</mat-icon></button>
+                </div>
+            </div>
+        </div>
+        <mat-hint style="margin-bottom: 10px;" *ngIf="existingTemplates.length === 0">(no templates available)</mat-hint>
+
+    </div>
+</div>
diff --git a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.scss
similarity index 95%
rename from ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss
rename to ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.scss
index 2c1a70e..c232acd 100644
--- a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss
+++ b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.scss
@@ -16,7 +16,7 @@
  *
  */
 
-@import '../../../../scss/sp/sp-dialog.scss';
+@import 'src/scss/sp/sp-dialog';
 
 .divider {
   margin-top: 10px;
diff --git a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.ts b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.ts
similarity index 76%
rename from ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.ts
rename to ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.ts
index a9e3064..e8a7f78 100644
--- a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.ts
+++ b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-config.component.ts
@@ -17,10 +17,10 @@
  */
 
 import { Component, Input, OnInit } from '@angular/core';
-import { InvocablePipelineElementUnion } from '../../model/editor.model';
 import {
+  PipelineElementTemplateService,
   PipelineElementTemplate,
-  StaticPropertyUnion
+  StaticPropertyUnion,
 } from '@streampipes/platform-services';
 import { PipelineElementTemplateGenerator } from './pipeline-element-template-generator';
 
@@ -32,22 +32,38 @@
 export class PipelineElementTemplateConfigComponent implements OnInit {
 
   @Input()
-  cachedPipelineElement: InvocablePipelineElementUnion;
-
-  @Input()
   template: PipelineElementTemplate;
 
   @Input()
   templateConfigs: Map<string, any>;
 
+  @Input()
+  appId: string;
+
+  @Input()
+  staticProperties: StaticPropertyUnion[];
+
+  existingTemplates: PipelineElementTemplate[];
+
+  constructor(private pipelineElementTemplateService: PipelineElementTemplateService) {
+
+  }
+
 
   ngOnInit(): void {
-    this.template.basePipelineElementAppId = this.cachedPipelineElement.appId;
-    this.cachedPipelineElement.staticProperties.forEach(sp => {
+    this.loadTemplates();
+    this.template.basePipelineElementAppId = this.appId;
+    this.staticProperties.forEach(sp => {
       this.templateConfigs.set(sp.internalName, this.makeTemplateValue(sp));
     });
   }
 
+  loadTemplates() {
+    this.pipelineElementTemplateService.getPipelineElementTemplates(this.appId).subscribe(templates => {
+      this.existingTemplates = templates;
+    });
+  }
+
   handleSelection(sp: StaticPropertyUnion) {
     if (this.templateConfigs.has(sp.internalName)) {
       this.templateConfigs.delete(sp.internalName);
@@ -76,4 +92,9 @@
     this.templateConfigs.set(sp.internalName, config);
   }
 
+  deleteTemplate(templateId: string) {
+    this.pipelineElementTemplateService
+      .deletePipelineElementTemplate(templateId).subscribe(result => this.loadTemplates());
+  }
+
 }
diff --git a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-generator.ts b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-generator.ts
similarity index 92%
rename from ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-generator.ts
rename to ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-generator.ts
index 72366e3..4d7c830 100644
--- a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-generator.ts
+++ b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template-generator.ts
@@ -27,7 +27,8 @@
   SecretStaticProperty,
   StaticPropertyAlternative,
   StaticPropertyAlternatives, StaticPropertyGroup,
-  StaticPropertyUnion
+  StaticPropertyUnion,
+  SlideToggleStaticProperty
 } from '@streampipes/platform-services';
 
 export class PipelineElementTemplateGenerator {
@@ -49,6 +50,8 @@
       return this.sp.options.filter(o => o.selected).map(o => o.name);
     } else if (this.sp instanceof CodeInputStaticProperty) {
       return this.sp.value;
+    } else if (this.sp instanceof SlideToggleStaticProperty) {
+      return this.sp.selected;
     } else if (this.sp instanceof CollectionStaticProperty) {
       return {
         members: this.addListEntry(this.sp.members)
@@ -60,9 +63,10 @@
         alternatives: this.addNestedEntry(this.sp.alternatives)
       };
     } else if (this.sp instanceof StaticPropertyAlternative) {
+      const sp = this.sp.staticProperty ? this.addNestedEntry([this.sp.staticProperty]) : {};
       return {
         selected: this.sp.selected,
-        staticProperty: this.addNestedEntry([this.sp.staticProperty])
+        staticProperty: sp
       };
     } else if (this.sp instanceof StaticPropertyGroup) {
       return { staticProperties: this.addNestedEntry(this.sp.staticProperties)};
diff --git a/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template.pipe.ts b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template.pipe.ts
new file mode 100644
index 0000000..f44b8aa
--- /dev/null
+++ b/ui/src/app/core-ui/pipeline-element-template-config/pipeline-element-template.pipe.ts
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable, Pipe, PipeTransform } from '@angular/core';
+import {
+  RuntimeResolvableAnyStaticProperty, RuntimeResolvableOneOfStaticProperty, RuntimeResolvableTreeInputStaticProperty,
+  StaticPropertyUnion
+} from '@streampipes/platform-services';
+
+@Pipe({name: 'pipelineElementTemplatePipe'})
+@Injectable({providedIn: 'root'})
+export class PipelineElementTemplatePipe implements PipeTransform {
+
+  transform(properties: StaticPropertyUnion[]): StaticPropertyUnion[] {
+
+    return properties.filter(p => (
+      !(p instanceof RuntimeResolvableAnyStaticProperty) &&
+      !(p instanceof RuntimeResolvableOneOfStaticProperty &&
+        !(p instanceof RuntimeResolvableTreeInputStaticProperty))));
+  }
+
+}
diff --git a/ui/src/app/core-ui/static-properties/static-file-input/static-file-input.component.html b/ui/src/app/core-ui/static-properties/static-file-input/static-file-input.component.html
index 6e3b6e4..19c514a 100644
--- a/ui/src/app/core-ui/static-properties/static-file-input/static-file-input.component.html
+++ b/ui/src/app/core-ui/static-properties/static-file-input/static-file-input.component.html
@@ -24,8 +24,8 @@
                 <mat-radio-button [value]="false">Upload new file</mat-radio-button>
             </mat-radio-group>
         </div>
-        <div *ngIf="chooseExistingFileControl.value && filesLoaded" >
-            <mat-form-field>
+        <div *ngIf="chooseExistingFileControl.value && filesLoaded" class="mt-10">
+            <mat-form-field color="accent" class="w-100">
                 <input type="text"
                        placeholder="Select file"
                        formControlName="{{fieldName}}"
@@ -34,7 +34,7 @@
                 <button mat-button *ngIf="selectedFile" matSuffix mat-icon-button aria-label="Clear" (click)="selectedFile={}">
                     <mat-icon>close</mat-icon>
                 </button>
-                <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selectOption($event.option.value)" [displayWith]="displayFn">
+                <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selectOption($event.option.value)" [displayWith]="displayFn" style="width: 50%;">
                     <mat-option *ngFor="let fileMetadata of fileMetadata" [value]="fileMetadata">
                         {{fileMetadata.originalFilename}}
                     </mat-option>
diff --git a/ui/src/app/core-ui/static-properties/static-free-input/static-free-input.component.ts b/ui/src/app/core-ui/static-properties/static-free-input/static-free-input.component.ts
index 15eff2f..fd3bb56 100644
--- a/ui/src/app/core-ui/static-properties/static-free-input/static-free-input.component.ts
+++ b/ui/src/app/core-ui/static-properties/static-free-input/static-free-input.component.ts
@@ -38,10 +38,10 @@
 
   quillModules: any = {
     toolbar: [['bold', 'italic', 'underline', 'strike'],
-      [{ 'header': 1 }, { 'header': 2 }],
-      [{ 'size': ['small', false, 'large', 'huge'] }],
-      [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
-      [{ 'color': [] }, { 'background': [] }]
+      [{'header': 1}, {'header': 2}],
+      [{'size': ['small', false, 'large', 'huge']}],
+      [{'header': [1, 2, 3, 4, 5, 6, false]}],
+      [{'color': []}, {'background': []}]
     ]
   };
 
@@ -50,7 +50,7 @@
     ]
   };
 
-  @ViewChild('textEditor', { static: false })
+  @ViewChild('textEditor', {static: false})
   quillEditorComponent: QuillEditorComponent;
 
   constructor(public staticPropertyUtil: StaticPropertyUtilService,
@@ -62,6 +62,7 @@
   ngOnInit() {
     this.addValidator(this.staticProperty.value, this.collectValidators());
     this.enableValidators();
+    this.emitUpdate();
   }
 
   collectValidators() {
@@ -83,7 +84,9 @@
   }
 
   emitUpdate() {
-    const valid = (this.staticProperty.value !== undefined && this.staticProperty.value !== '');
+    const valid = (this.staticProperty.value !== undefined &&
+      this.staticProperty.value !== '' &&
+      this.staticProperty.value !== null);
     this.updateEmitter.emit(new ConfigurationInfo(this.staticProperty.internalName, valid));
   }
 
diff --git a/ui/src/app/core-ui/static-properties/static-property.component.html b/ui/src/app/core-ui/static-properties/static-property.component.html
index 308ce51..c7d8967 100644
--- a/ui/src/app/core-ui/static-properties/static-property.component.html
+++ b/ui/src/app/core-ui/static-properties/static-property.component.html
@@ -68,6 +68,7 @@
                                                      [staticProperties]="staticProperties"
                                                      [eventSchemas]="eventSchemas"
                                                      [pipelineElement]="pipelineElement"
+                                                     [parentForm]="parentForm"
                                                      [completedStaticProperty]="completedStaticProperty"
                                                      [adapterId]="adapterId">
             </app-static-runtime-resolvable-any-input>
@@ -77,6 +78,7 @@
                                                        [pipelineElement]="pipelineElement"
                                                        [eventSchemas]="eventSchemas"
                                                        [staticProperty]="staticProperty"
+                                                       [parentForm]="parentForm"
                                                        [staticProperties]="staticProperties"
                                                        [adapterId]="adapterId"></app-static-runtime-resolvable-oneof-input>
 
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
index 211cce1..9e287ba 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
@@ -32,7 +32,7 @@
             {{option.name}}
         </mat-checkbox>
     </div>
-    <div fxLayout="column" *ngIf="!showOptions && !loading">
+    <div fxLayout="column" *ngIf="!showOptions && !loading" class="mt-10">
         <span>(waiting for input)</span>
     </div>
     <div fxLayout="column" *ngIf="loading">
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
index b24bc7a..c1589be 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
@@ -53,4 +53,7 @@
         return staticProperty as RuntimeResolvableAnyStaticProperty;
     }
 
+    afterErrorReceived() {
+    }
+
 }
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-input/base-runtime-resolvable-input.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-input/base-runtime-resolvable-input.ts
index 229beba..b2f33e3 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-input/base-runtime-resolvable-input.ts
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-input/base-runtime-resolvable-input.ts
@@ -30,6 +30,7 @@
 import { Observable } from 'rxjs';
 import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core';
 import { ConfigurationInfo } from '../../../connect/model/ConfigurationInfo';
+import { StreamPipesErrorMessage } from '../../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
 
 @Directive()
 // tslint:disable-next-line:directive-class-suffix
@@ -43,6 +44,8 @@
 
   showOptions = false;
   loading = false;
+  error = false;
+  errorMessage: StreamPipesErrorMessage;
   dependentStaticProperties: any = new Map();
 
   constructor(private runtimeResolvableService: RuntimeResolvableService) {
@@ -70,6 +73,8 @@
 
     this.showOptions = false;
     this.loading = true;
+    this.error = false;
+    this.errorMessage = undefined;
     const observable: Observable<RuntimeOptionsResponse> = this.adapterId ?
       this.runtimeResolvableService.fetchRemoteOptionsForAdapter(resolvableOptionsParameterRequest, this.adapterId) :
       this.runtimeResolvableService.fetchRemoteOptionsForPipelineElement(resolvableOptionsParameterRequest);
@@ -80,6 +85,12 @@
       }
       this.loading = false;
       this.showOptions = true;
+    }, errorMessage => {
+      this.loading = false;
+      this.showOptions = true;
+      this.error = true;
+      this.errorMessage = errorMessage.error as StreamPipesErrorMessage;
+      this.afterErrorReceived();
     });
   }
 
@@ -107,4 +118,6 @@
 
   abstract afterOptionsLoaded(staticProperty: T);
 
+  abstract afterErrorReceived();
+
 }
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.html b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.html
index e58f8ad..3f1ff10 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.html
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.html
@@ -16,7 +16,7 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="100" fxLayout="column">
+<div [formGroup]="parentForm" id="formWrapper" fxFlex="100" fxLayout="column">
     <div>
         <button mat-button mat-raised-button color="accent" class="small-button"
                 data-cy="sp-reload"
@@ -26,7 +26,10 @@
             <span>Reload</span>
         </button>
     </div>
-    <div *ngIf="!staticProperty.horizontalRendering" fxLayout="column">
+    <div fxLayout="column" *ngIf="error" class="mt-10">
+        <sp-exception-message [message]="errorMessage"></sp-exception-message>
+    </div>
+    <div *ngIf="!loading" fxLayout="column">
         <div fxFlex fxLayout="row">
             <div fxLayout="column" *ngIf="showOptions || staticProperty.options" style="margin-left: 10px">
                 <mat-radio-button *ngFor="let option of staticProperty.options"
@@ -38,7 +41,7 @@
                     </label>
                 </mat-radio-button>
             </div>
-            <div fxLayout="column" *ngIf="!showOptions && !loading">
+            <div fxLayout="column" *ngIf="!showOptions && !loading" class="mt-10">
                 <span>(waiting for input)</span>
             </div>
             <div fxLayout="column" *ngIf="loading">
@@ -49,21 +52,4 @@
             </div>
         </div>
     </div>
-
-    <div *ngIf="staticProperty.horizontalRendering">
-        <mat-form-field style="width: 100%">
-            <mat-label>{{staticProperty.label}}</mat-label>
-            <span matPrefix *ngIf="loading"><mat-spinner style="top:5px" [diameter]="20"></mat-spinner></span>
-            <mat-select>
-                <mat-option *ngFor="let option of staticProperty.options" [value]="option.elementId"
-                            (click)="select(option.elementId)">
-                    <label style="font-weight: normal">
-                        {{option.name}}
-                    </label>
-                </mat-option>
-            </mat-select>
-            <mat-hint>{{staticProperty.description}}</mat-hint>
-        </mat-form-field>
-    </div>
-
 </div>
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.ts
index a6c12b1..f5b973c 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.ts
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.ts
@@ -20,6 +20,7 @@
 import { RuntimeResolvableOneOfStaticProperty, StaticPropertyUnion } from '@streampipes/platform-services';
 import { RuntimeResolvableService } from '../static-runtime-resolvable-input/runtime-resolvable.service';
 import { BaseRuntimeResolvableSelectionInput } from '../static-runtime-resolvable-input/base-runtime-resolvable-selection-input';
+import { FormControl } from '@angular/forms';
 
 @Component({
     selector: 'app-static-runtime-resolvable-oneof-input',
@@ -35,6 +36,8 @@
 
     ngOnInit() {
         super.onInit();
+        this.parentForm.addControl(this.staticProperty.internalName, new FormControl(this.staticProperty.options, []));
+        this.performValidation();
     }
 
     afterOptionsLoaded(staticProperty: RuntimeResolvableOneOfStaticProperty) {
@@ -49,9 +52,24 @@
             option.selected = false;
         }
         this.staticProperty.options.find(option => option.elementId === id).selected = true;
+        this.performValidation();
     }
 
     parse(staticProperty: StaticPropertyUnion): RuntimeResolvableOneOfStaticProperty {
         return staticProperty as RuntimeResolvableOneOfStaticProperty;
     }
+
+    afterErrorReceived() {
+        this.staticProperty.options = [];
+        this.performValidation();
+    }
+
+    performValidation() {
+        let error = {error: true};
+        if (this.staticProperty.options && this.staticProperty.options.find(o => o.selected) !== undefined) {
+            error = undefined;
+        }
+        console.log(error);
+        this.parentForm.controls[this.staticProperty.internalName].setErrors(error);
+    }
 }
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input.component.html b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input.component.html
index 753c76a..49e036d 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input.component.html
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input.component.html
@@ -20,10 +20,18 @@
     <div>
         <button mat-button mat-raised-button color="accent" class="small-button"
                 (click)="loadOptionsFromRestApi()"
-                style="margin-right:10px;margin-left:10px;" [disabled]="!showOptions">
+                style="margin-right:10px;" [disabled]="!showOptions">
             <span>Reload</span>
         </button>
     </div>
+    <div fxLayout="column" *ngIf="loading" class="mt-10">
+        <mat-spinner color="accent"
+                     [mode]="'indeterminate'"
+                     [diameter]="20"></mat-spinner>
+    </div>
+    <div fxLayout="column" *ngIf="error" class="mt-10">
+        <sp-exception-message [message]="errorMessage"></sp-exception-message>
+    </div>
     <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="sp-tree">
         <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
             <mat-checkbox color="accent"
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input.component.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input.component.ts
index 3be9378..cb2fa18 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input.component.ts
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input.component.ts
@@ -26,6 +26,7 @@
 import { RuntimeResolvableService } from '../static-runtime-resolvable-input/runtime-resolvable.service';
 import { NestedTreeControl } from '@angular/cdk/tree';
 import { MatTreeNestedDataSource } from '@angular/material/tree';
+import { AbstractControl, FormControl, ValidationErrors, ValidatorFn } from '@angular/forms';
 
 @Component({
   selector: 'sp-runtime-resolvable-tree-input',
@@ -55,6 +56,7 @@
       this.showOptions = true;
     }
     super.onInit();
+    this.parentForm.addControl(this.staticProperty.internalName, new FormControl(this.staticProperty.nodes, []));
   }
 
   parse(staticProperty: StaticPropertyUnion): RuntimeResolvableTreeInputStaticProperty {
@@ -64,10 +66,12 @@
   afterOptionsLoaded(staticProperty: RuntimeResolvableTreeInputStaticProperty) {
     this.staticProperty.nodes = staticProperty.nodes;
     this.dataSource.data = this.staticProperty.nodes;
+    this.performValidation();
   }
 
   toggleNodeSelection(node: TreeInputNode) {
     node.selected = !node.selected;
+    this.performValidation();
   }
 
   toggleAllNodeSelection(node: any) {
@@ -75,6 +79,7 @@
     const newState = !node.selected;
     node.selected = newState;
     descendants.forEach(d => d.selected = newState);
+    this.performValidation();
   }
 
   descendantsAllSelected(node: TreeInputNode) {
@@ -93,4 +98,30 @@
     return result && !this.descendantsAllSelected(node);
   }
 
+  performValidation() {
+    let error = {error: true};
+    if (this.anyNodeSelected()) {
+      error = undefined;
+    }
+    this.parentForm.controls[this.staticProperty.internalName].setErrors(error);
+  }
+
+  anyNodeSelected(): boolean {
+    return this.dataSource.data.find(d => this.anySelected(d)) !== undefined;
+  }
+
+  anySelected(node: TreeInputNode): boolean {
+    if (node.selected) {
+      return true;
+    } else {
+      return node.children.find(n => this.anySelected(n)) !== undefined;
+    }
+  }
+
+  afterErrorReceived() {
+    this.staticProperty.nodes = [];
+    this.dataSource.data = [];
+    this.performValidation();
+  }
+
 }
diff --git a/ui/src/app/core-ui/static-properties/static-secret-input/static-secret-input.component.html b/ui/src/app/core-ui/static-properties/static-secret-input/static-secret-input.component.html
index 54f9ac5..4206ab8 100644
--- a/ui/src/app/core-ui/static-properties/static-secret-input/static-secret-input.component.html
+++ b/ui/src/app/core-ui/static-properties/static-secret-input/static-secret-input.component.html
@@ -18,7 +18,7 @@
 
 <div [formGroup]="parentForm" id="formWrapper" fxFlex="100" fxLayout="column">
     <div fxFlex="100" fxLayout="row">
-        <mat-form-field fxFlex>
+        <mat-form-field fxFlex color="accent">
             <input type="password"
                    fxFlex
                    formControlName="{{fieldName}}"
@@ -34,4 +34,4 @@
             </mat-error>
         </mat-form-field>
     </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/ui/src/app/core/components/breadcrumb/breadcrumb.component.html b/ui/src/app/core/components/breadcrumb/breadcrumb.component.html
new file mode 100644
index 0000000..c605f1f
--- /dev/null
+++ b/ui/src/app/core/components/breadcrumb/breadcrumb.component.html
@@ -0,0 +1,30 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="column" fxFlex="100" class="breadcrumb-outer" fxLayoutAlign="center start">
+    <div fxLayout="row" fxLayoutAlign="start center">
+        <div [ngClass]="currentNavItems.length > 0 ? 'bc-item' : 'mat-hint'" fxLayout="row" fxLayoutAlign="start center" (click)="navigateTo([''])">
+            <mat-icon fxLayoutAlign="start center" class="divider">home</mat-icon>
+            <div>&nbsp;Home</div>
+        </div>
+        <div *ngFor="let bcItem of currentNavItems" fxLayout="row" fxLayoutAlign="start center">
+            <mat-icon fxLayoutAlign="start center" class="divider mat-hint">arrow_right</mat-icon>
+            <div [ngClass]="bcItem.link ? 'bc-item' : 'mat-hint'" (click)="navigateTo(bcItem.link)">{{bcItem.label}}</div>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss b/ui/src/app/core/components/breadcrumb/breadcrumb.component.scss
similarity index 76%
copy from ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss
copy to ui/src/app/core/components/breadcrumb/breadcrumb.component.scss
index 2c1a70e..d3b603e 100644
--- a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.scss
+++ b/ui/src/app/core/components/breadcrumb/breadcrumb.component.scss
@@ -16,19 +16,21 @@
  *
  */
 
-@import '../../../../scss/sp/sp-dialog.scss';
+.breadcrumb-outer {
+  margin: 10px 10px 0 10px;
+  max-height: 20px;
+  height: 20px;
+  font-size: 10pt;
+  color: var(--color-accent);
+}
 
 .divider {
-  margin-top: 10px;
-  margin-bottom: 10px;
+  font-size: 10pt;
+  width: 10pt;
+  height: 10pt;
 }
 
-.static-property-panel {
-  padding-left: 10px;
-  margin-bottom: 10px;
-  margin-top: 10px;
-}
-
-.static-property-panel-border {
-  border-left:5px solid gray;
+.bc-item:hover {
+  color: var(--color-primary);
+  cursor: pointer;
 }
diff --git a/ui/src/app/core/components/breadcrumb/breadcrumb.component.ts b/ui/src/app/core/components/breadcrumb/breadcrumb.component.ts
new file mode 100644
index 0000000..17c8488
--- /dev/null
+++ b/ui/src/app/core/components/breadcrumb/breadcrumb.component.ts
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { SpBreadcrumbItem, SpBreadcrumbService } from '@streampipes/shared-ui';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'sp-breadcrumb',
+  templateUrl: './breadcrumb.component.html',
+  styleUrls: ['./breadcrumb.component.scss']
+})
+export class SpBreadcrumbComponent implements OnInit {
+
+  currentNavItems: SpBreadcrumbItem[] = [];
+
+  constructor(private breadcrumbService: SpBreadcrumbService,
+              private router: Router) {
+
+  }
+
+  ngOnInit(): void {
+    this.breadcrumbService.currentNavHierarchy$.subscribe(currentNavItems => {
+      this.currentNavItems = currentNavItems;
+    });
+  }
+
+  navigateTo(target: string[]) {
+    this.router.navigate(target);
+  }
+
+
+
+}
diff --git a/ui/src/app/core/components/feedback/feedback.component.html b/ui/src/app/core/components/feedback/feedback.component.html
deleted file mode 100644
index 781c749..0000000
--- a/ui/src/app/core/components/feedback/feedback.component.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div class="feedback-container" (click) = "$event.stopPropagation()">
-    <div fxLayout="column" fxFlex="100" *ngIf="!sendingFeedback">
-        <div fxLayout="column" fxFlex="50" fxLayoutAlign="start center">
-            <div class="feedback-title">We welcome your feedback!</div>
-        </div>
-        <div fxLayout="column" fxFlex="40" fxLayoutAlign="start center" style="margin-bottom:20px;">
-            <div fxFlex="100" class="feedback-explainer">
-                <span>Your feedback helps us to improve {{appConstants.APP_NAME}}.<br/></span>
-                <span>Features you'd like to see, bugs you've found or things you like - tell us what you think!</span>
-            </div>
-        </div>
-        <div fxLayout="column" fxFlex="40" fxLayoutAlign="start center" style="margin-bottom:20px;">
-            <mat-form-field class="feedback-width-100 feedback-font-size-small" color="accent">
-                <label>Your feedback</label>
-                <textarea matInput [(ngModel)]="feedback.feedbackText" maxlength="500" rows="5"></textarea>
-            </mat-form-field>
-        </div>
-        <div fxLayout="column" fxFlex="40" fxLayoutAlign="end center">
-            <div fxLayout="row" fxLayoutAlign="end end">
-                <button mat-button mat-raised-button class="mat-basic" (click)="closeDialog()" style="margin-right:10px;">
-                    Close
-                </button>
-                <button mat-button mat-raised-button color="accent" type="submit"
-                           (click)="sendMail()">
-                    Send Mail
-                </button>
-            </div>
-        </div>
-    </div>
-    <div fxFlex="100" fxLayout="column" *ngIf="sendingFeedback" class="feedback-height-100">
-        <div *ngIf="!sendingFeedbackFinished" class="feedback-height-100">
-            <div fxLayout="column" fxLayoutAlign="center center" fxFlex="100" fxLayoutFill>
-                <mat-spinner [mode]="'indeterminate'" [diameter]="96"></mat-spinner>
-                <div class="feedback-status">Submitting feedback...</div>
-            </div>
-        </div>
-        <div *ngIf="sendingFeedbackFinished" fxFlex="100" class="feedback-height-100">
-            <div fxLayout="column" fxLayoutAlign="center center" fxFlex="100" fxLayoutFill>
-                <div class="feedback-status">Thanks!</div>
-                <button mat-button mat-raised-button class="mat-basic" (click)="closeDialog()">
-                    Close
-                </button>
-            </div>
-        </div>
-    </div>
-</div>
diff --git a/ui/src/app/core/components/feedback/feedback.component.ts b/ui/src/app/core/components/feedback/feedback.component.ts
deleted file mode 100644
index e27e46a..0000000
--- a/ui/src/app/core/components/feedback/feedback.component.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, EventEmitter, OnInit, Output } from '@angular/core';
-import { AppConstants } from '../../../services/app.constants';
-
-@Component({
-    selector: 'feedback',
-    templateUrl: './feedback.component.html',
-})
-export class FeedbackComponent implements OnInit {
-
-    @Output()
-    closeFeedbackEmitter: EventEmitter<void> = new EventEmitter<void>();
-
-    feedback: any = {};
-
-    sendingFeedback = false;
-    sendingFeedbackFinished = false;
-
-    // deactivate direct feedback for Apache transition
-    feedbackUrl = '';
-    debugFeedbackUrl = '';
-
-    targetEmail: string;
-
-    constructor(public appConstants: AppConstants) {
-        this.targetEmail = appConstants.EMAIL;
-    }
-
-    ngOnInit() {
-        this.sendingFeedback = false;
-        this.sendingFeedbackFinished = false;
-    }
-
-    closeDialog() {
-        this.closeFeedbackEmitter.emit();
-        this.sendingFeedback = false;
-        this.sendingFeedbackFinished = false;
-    }
-
-    sendMail() {
-        this.sendingFeedback = true;
-        window.open('mailto:' + this.targetEmail + '?subject=' + '[USER-FEEDBACK]' + '&body=' + this.feedback.feedbackText, '_self');
-        this.sendingFeedbackFinished = true;
-    }
-}
diff --git a/ui/src/app/core/components/iconbar/iconbar.component.html b/ui/src/app/core/components/iconbar/iconbar.component.html
index a04b784..4cd727d 100644
--- a/ui/src/app/core/components/iconbar/iconbar.component.html
+++ b/ui/src/app/core/components/iconbar/iconbar.component.html
@@ -28,19 +28,7 @@
         </button>
         </div>
     </div>
-    <div [ngClass]="'notifications' === activePage ? 'sp-navbar-item-selected' : 'sp-navbar-item'"
-         style="padding-top:5px;padding-bottom:5px;" *ngIf="notificationsVisible">
-        <button mat-button mat-icon-button class="md-icon-button button-margin-iconbar iconbar-size"
-                (click)="go('notifications')"
-                matTooltip="Notifications" matTooltipPosition="right">
-            <mat-icon [matBadge]="unreadNotificationCount"
-                      [matBadgeHidden]="unreadNotificationCount == 0"
-                      [ngClass]="'notifications' === activePage ?'sp-navbar-icon-selected' : 'sp-navbar-icon'"
-                      data-cy="navigation-icon">chat
 
-            </mat-icon>
-        </button>
-    </div>
     <mat-divider style="border-top-color:var(--color-navigation-text);"></mat-divider>
     <div *ngFor="let item of admin" >
         <div  [ngClass]="item.link === activePage ? 'sp-navbar-item-selected' : 'sp-navbar-item'"
@@ -48,7 +36,7 @@
               *ngIf="item.visible">
             <button mat-button mat-icon-button class="md-icon-button button-margin-iconbar iconbar-size"
                     (click)="go(item.link)"
-                    matTooltip="{{item.title}}" >
+                    matTooltip="{{item.title}}" matTooltipPosition="right" >
                 <mat-icon
                         [ngClass]="item.link === activePage ?'sp-navbar-icon-selected' : 'sp-navbar-icon'"
                         data-cy="navigation-icon">{{item.icon}}</mat-icon>
diff --git a/ui/src/app/core/components/iconbar/iconbar.component.ts b/ui/src/app/core/components/iconbar/iconbar.component.ts
index c775ce9..9d7aeea 100644
--- a/ui/src/app/core/components/iconbar/iconbar.component.ts
+++ b/ui/src/app/core/components/iconbar/iconbar.component.ts
@@ -21,41 +21,29 @@
 import { Router } from '@angular/router';
 import { NotificationCountService } from '../../../services/notification-count-service';
 import { AuthService } from '../../../services/auth.service';
-import { Subscription, timer } from "rxjs";
-import { exhaustMap, mergeMap } from "rxjs/operators";
-import { RestApi } from "../../../services/rest-api.service";
+import { Subscription, timer } from 'rxjs';
+import { exhaustMap } from 'rxjs/operators';
+import { RestApi } from '../../../services/rest-api.service';
+import { AppConstants } from '../../../services/app.constants';
 
 @Component({
   selector: 'iconbar',
   templateUrl: './iconbar.component.html',
   styleUrls: ['./iconbar.component.scss']
 })
-export class IconbarComponent extends BaseNavigationComponent implements OnInit, OnDestroy {
+export class IconbarComponent extends BaseNavigationComponent implements OnInit {
 
-  unreadNotificationCount = 0;
-  unreadNotificationsSubscription: Subscription;
 
   constructor(router: Router,
               authService: AuthService,
               public notificationCountService: NotificationCountService,
-              private restApi: RestApi) {
-    super(authService, router);
+              private restApi: RestApi,
+              appConstants: AppConstants) {
+    super(authService, router, appConstants);
   }
 
   ngOnInit(): void {
     super.onInit();
-    this.unreadNotificationsSubscription = timer(0, 10000).pipe(
-      exhaustMap(() => this.restApi.getUnreadNotificationsCount()))
-      .subscribe(response => {
-        this.notificationCountService.unreadNotificationCount$.next(response.count);
-      });
 
-    this.notificationCountService.unreadNotificationCount$.subscribe(count => {
-      this.unreadNotificationCount = count;
-    });
-  }
-
-  ngOnDestroy() {
-    this.unreadNotificationsSubscription.unsubscribe();
   }
 }
diff --git a/ui/src/app/core/components/streampipes/streampipes.component.html b/ui/src/app/core/components/streampipes/streampipes.component.html
index 168f6e2..7ff132b 100644
--- a/ui/src/app/core/components/streampipes/streampipes.component.html
+++ b/ui/src/app/core/components/streampipes/streampipes.component.html
@@ -25,6 +25,7 @@
             <iconbar></iconbar>
         </div>
         <div style="width: 100%; height: 100%; overflow-y: auto;" class="base">
+            <sp-breadcrumb></sp-breadcrumb>
             <router-outlet></router-outlet>
         </div>
     </div>
diff --git a/ui/src/app/core/components/toolbar/toolbar.component.html b/ui/src/app/core/components/toolbar/toolbar.component.html
index 6ee8046..2767609 100644
--- a/ui/src/app/core/components/toolbar/toolbar.component.html
+++ b/ui/src/app/core/components/toolbar/toolbar.component.html
@@ -18,39 +18,33 @@
 
 <mat-toolbar class="md-primary md-hue-2 top-nav toolbar-bg">
     <div class="md-toolbar-tools sp-toolbar">
-        <div fxFlex="60" fxLayout fxLayoutAlign="start center">
+        <div fxFlex="100" fxLayout fxLayoutAlign="start center">
             <div class="md-toolbar-tools" style="height:40px;max-height:40px;" fxFlex fxLayout="row" fxLayoutAlign="start center">
                 <div style="padding:5px;border-radius:0px;margin-right:15px;position:relative;left:20px;">
-                    <img alt="icon" src="../../../../assets/img/sp/logo-navigation.png" style="height:30px;">
-                </div>
-                <div style="margin-left:30px;">
-                    <span class="active-page">{{activePageName}}</span>
+                    <img alt="icon" src="../../../../assets/img/sp/logo-navigation.png" style="max-height:30px;max-width: 250px;">
                 </div>
             </div>
-        </div>
-        <span fxFlex></span>
-        <div fxFlex="40" fxLayout fxLayoutAlign="end center" *ngIf="authenticated" style="height:100%;">
-            <div fxLayoutAlign="start center" *ngIf="versionInfo && versionInfo.backendVersion">
-                <span class="version-info-text">v{{versionInfo.backendVersion}}</span>
-            </div>
+        <div fxFlex fxLayout fxLayoutAlign="end center" *ngIf="authenticated" style="height:100%;">
             <!-- uncomment this to quickly investigate layout issues between dark and light mode -->
 <!--            <div>-->
 <!--                <mat-slide-toggle color="accent" [formControl]="appearanceControl">Dark Mode</mat-slide-toggle>-->
 <!--            </div>-->
-            <div style="height:100%;">
-                <div [ngClass]="feedbackOpen.menuOpen ? 'sp-navbar-item-selected' : 'sp-navbar-item'" fxLayout fxLayoutAlign="center center" style="height: 100%;">
-                    <button mat-button mat-icon-button
-                            [matMenuTriggerFor]="feedbackMenu"
-                            #feedbackOpen="matMenuTrigger"
-                            matTooltip="Feedback" matTooltipPosition="below"
-                            [ngClass]="feedbackOpen.menuOpen ? 'sp-icon-button-no-hover' : 'sp-icon-button'" style="min-width:0px;" fxLayout fxLayoutAlign="center center">
-                        <i [ngClass]="feedbackOpen.menuOpen ? 'sp-navbar-icon-selected' : 'sp-navbar-icon'" class="material-icons">feedback</i>
-                    </button>
-                </div>
+            <div [ngClass]="'notifications' === activePage ? 'sp-navbar-item-selected' : 'sp-navbar-item'"
+                 *ngIf="notificationsVisible" class="h-100">
+                <button mat-button mat-icon-button class="md-icon-button button-margin-iconbar iconbar-size"
+                        (click)="go('notifications')"
+                        fxLayout fxLayoutAlign="center center"
+                        matTooltip="Notifications" matTooltipPosition="below">
+                    <mat-icon [matBadge]="unreadNotificationCount"
+                              matBadgeColor="accent"
+                              matBadgePosition="below after"
+                              [matBadgeHidden]="unreadNotificationCount == 0"
+                              [ngClass]="'notifications' === activePage ?'sp-navbar-icon-selected' : 'sp-navbar-icon'"
+                              data-cy="navigation-icon">chat
+
+                    </mat-icon>
+                </button>
             </div>
-            <mat-menu #feedbackMenu="matMenu" style="max-width: none;" class="feedback-menu-content">
-                <feedback (closeFeedbackEmitter)="closeFeedbackWindow()"></feedback>
-            </mat-menu>
             <div style="height:100%;">
                 <div [ngClass]="accountMenuOpen.menuOpen ? 'sp-navbar-item-selected' : 'sp-navbar-item'" fxLayout fxLayoutAlign="center center" style="height: 100%;">
                     <button mat-button mat-icon-button
@@ -91,5 +85,6 @@
                 </button>
             </mat-menu>
         </div>
+        </div>
     </div>
 </mat-toolbar>
diff --git a/ui/src/app/core/components/toolbar/toolbar.component.ts b/ui/src/app/core/components/toolbar/toolbar.component.ts
index ee52a28..d476b91 100644
--- a/ui/src/app/core/components/toolbar/toolbar.component.ts
+++ b/ui/src/app/core/components/toolbar/toolbar.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, OnInit, ViewChild } from '@angular/core';
+import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
 import { BaseNavigationComponent } from '../base-navigation.component';
 import { Router } from '@angular/router';
 import { RestApi } from '../../../services/rest-api.service';
@@ -24,35 +24,50 @@
 import { FormControl } from '@angular/forms';
 import { OverlayContainer } from '@angular/cdk/overlay';
 import { ProfileService } from '../../../profile/profile.service';
-import { VersionInfo } from '../../../info/versions/service/version-info.model';
 import { AuthService } from '../../../services/auth.service';
+import { AppConstants } from '../../../services/app.constants';
+import { Subscription, timer } from 'rxjs';
+import { exhaustMap } from 'rxjs/operators';
+import { NotificationCountService } from '../../../services/notification-count-service';
 
 @Component({
   selector: 'toolbar',
   templateUrl: './toolbar.component.html',
   styleUrls: ['./toolbar.component.scss']
 })
-export class ToolbarComponent extends BaseNavigationComponent implements OnInit {
+export class ToolbarComponent extends BaseNavigationComponent implements OnInit, OnDestroy {
 
   @ViewChild('feedbackOpen') feedbackOpen: MatMenuTrigger;
   @ViewChild('accountMenuOpen') accountMenuOpen: MatMenuTrigger;
 
   userEmail;
-  versionInfo: VersionInfo;
   darkMode: boolean;
 
   appearanceControl: FormControl;
 
+  unreadNotificationCount = 0;
+  unreadNotificationsSubscription: Subscription;
+
   constructor(router: Router,
               private profileService: ProfileService,
               private restApi: RestApi,
               private overlay: OverlayContainer,
-              authService: AuthService) {
-    super(authService, router);
+              authService: AuthService,
+              appConstants: AppConstants,
+              public notificationCountService: NotificationCountService) {
+    super(authService, router, appConstants);
   }
 
   ngOnInit(): void {
-    this.getVersion();
+    this.unreadNotificationsSubscription = timer(0, 10000).pipe(
+      exhaustMap(() => this.restApi.getUnreadNotificationsCount()))
+      .subscribe(response => {
+        this.notificationCountService.unreadNotificationCount$.next(response.count);
+      });
+
+    this.notificationCountService.unreadNotificationCount$.subscribe(count => {
+      this.unreadNotificationCount = count;
+    });
     this.authService.user$.subscribe(user => {
       this.userEmail = user.displayName;
       this.profileService.getUserProfile(user.username).subscribe(userInfo => {
@@ -79,11 +94,6 @@
     }
   }
 
-  closeFeedbackWindow() {
-    // this.feedbackOpen = false;
-    this.feedbackOpen.closeMenu();
-  }
-
   openDocumentation() {
     window.open('https://streampipes.apache.org/docs', '_blank');
   }
@@ -103,10 +113,8 @@
     this.router.navigate(['login']);
   }
 
-  getVersion() {
-    this.restApi.getVersionInfo().subscribe((response) => {
-      this.versionInfo = response as VersionInfo;
-    });
+  ngOnDestroy() {
+    this.unreadNotificationsSubscription.unsubscribe();
   }
 
 }
diff --git a/ui/src/app/core/core.module.ts b/ui/src/app/core/core.module.ts
index 956182f..84ee547 100644
--- a/ui/src/app/core/core.module.ts
+++ b/ui/src/app/core/core.module.ts
@@ -22,7 +22,6 @@
 import { FlexLayoutModule } from '@angular/flex-layout';
 import { CommonModule } from '@angular/common';
 import { StreampipesComponent } from './components/streampipes/streampipes.component';
-import { FeedbackComponent } from './components/feedback/feedback.component';
 import { MatButtonModule } from '@angular/material/button';
 import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
 import { MatInputModule } from '@angular/material/input';
@@ -37,34 +36,37 @@
 import { MatMenuModule } from '@angular/material/menu';
 import { MatBadgeModule } from '@angular/material/badge';
 import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { SpBreadcrumbComponent } from './components/breadcrumb/breadcrumb.component';
+import { SharedUiModule } from '@streampipes/shared-ui';
 
 @NgModule({
-    imports: [
-        CommonModule,
-        FlexLayoutModule,
-        MatGridListModule,
-        MatDividerModule,
-        MatListModule,
-        MatIconModule,
-        MatMenuModule,
-        MatBadgeModule,
-        MatButtonModule,
-        MatTooltipModule,
-        MatProgressSpinnerModule,
-        MatInputModule,
-        MatToolbarModule,
-        FormsModule,
-        RouterModule,
-        MatSlideToggleModule,
-        ReactiveFormsModule
-    ],
-    declarations: [
-        StreampipesComponent,
-        FeedbackComponent,
-        IconbarComponent,
-        ToolbarComponent
-    ],
-    providers: []
+  imports: [
+    CommonModule,
+    FlexLayoutModule,
+    MatGridListModule,
+    MatDividerModule,
+    MatListModule,
+    MatIconModule,
+    MatMenuModule,
+    MatBadgeModule,
+    MatButtonModule,
+    MatTooltipModule,
+    MatProgressSpinnerModule,
+    MatInputModule,
+    MatToolbarModule,
+    FormsModule,
+    RouterModule,
+    MatSlideToggleModule,
+    ReactiveFormsModule,
+    SharedUiModule
+  ],
+  declarations: [
+    SpBreadcrumbComponent,
+    StreampipesComponent,
+    IconbarComponent,
+    ToolbarComponent
+  ],
+  providers: []
 })
 export class CoreModule {
 }
diff --git a/ui/src/app/dashboard/components/grid/dashboard-grid.component.html b/ui/src/app/dashboard/components/grid/dashboard-grid.component.html
index d0d3795..de987ce 100644
--- a/ui/src/app/dashboard/components/grid/dashboard-grid.component.html
+++ b/ui/src/app/dashboard/components/grid/dashboard-grid.component.html
@@ -16,18 +16,21 @@
   ~
   -->
 
-<div *ngIf="dashboard.displayHeader" class="text-center">
+<div *ngIf="dashboard && dashboard.displayHeader" class="text-center">
     <h2>{{dashboard.name}}</h2>
     <h3>{{dashboard.description}}</h3>
 </div>
 <gridster [options]="options" [ngClass]="editMode ? 'edit' : ''">
     <ng-container *ngFor="let item of dashboard.widgets;let i=index">
         <gridster-item [item]="item" #gridsterItemComponent>
-            <dashboard-widget (updateCallback)="propagateItemUpdate($event)"
+            <dashboard-widget (updateCallback)="propagateItemUpdate($event)" #dashboardWidgetComponent
                               (deleteCallback)="propagateItemRemoval($event)"
                               [widget]="item"
                               [editMode]="editMode"
+                              [allMeasurements]="allMeasurements"
+                              [globalRefresh]="dashboard.dashboardGeneralSettings.globalRefresh"
                               [headerVisible]="headerVisible"
+                              [gridsterItemComponent]="gridsterItemComponent"
                               [itemWidth]="gridsterItemComponent.width"
                               [itemHeight]="gridsterItemComponent.height"
             ></dashboard-widget>
diff --git a/ui/src/app/dashboard/components/grid/dashboard-grid.component.ts b/ui/src/app/dashboard/components/grid/dashboard-grid.component.ts
index c31211d..443aa49 100644
--- a/ui/src/app/dashboard/components/grid/dashboard-grid.component.ts
+++ b/ui/src/app/dashboard/components/grid/dashboard-grid.component.ts
@@ -17,80 +17,145 @@
  */
 
 import {
-    Component,
-    EventEmitter,
-    Input,
-    OnChanges,
-    OnInit,
-    Output,
-    QueryList,
-    SimpleChanges,
-    ViewChildren
+  AfterContentInit,
+  Component,
+  EventEmitter,
+  Input,
+  OnChanges, OnDestroy,
+  OnInit,
+  Output,
+  QueryList,
+  SimpleChanges,
+  ViewChildren
 } from '@angular/core';
-import { Dashboard, DashboardConfig, DashboardItem, DashboardWidgetModel } from '@streampipes/platform-services';
+import {
+  Dashboard,
+  DashboardConfig,
+  DashboardItem,
+  DashboardWidgetModel, DataLakeMeasure,
+  DatalakeRestService, SpQueryResult
+} from '@streampipes/platform-services';
 import { ResizeService } from '../../services/resize.service';
 import { GridsterItemComponent, GridType } from 'angular-gridster2';
+import { GridsterInfo } from "../../models/gridster-info.model";
+import { DashboardWidgetComponent } from '../widget/dashboard-widget.component';
+import { exhaustMap } from 'rxjs/operators';
+import { Observable, of, Subscription, timer } from 'rxjs';
 
 @Component({
-    selector: 'dashboard-grid',
-    templateUrl: './dashboard-grid.component.html',
-    styleUrls: ['./dashboard-grid.component.css']
+  selector: 'dashboard-grid',
+  templateUrl: './dashboard-grid.component.html',
+  styleUrls: ['./dashboard-grid.component.css']
 })
-export class DashboardGridComponent implements OnInit, OnChanges {
+export class DashboardGridComponent implements OnInit, OnChanges, AfterContentInit, OnDestroy {
 
-    @Input() editMode: boolean;
-    @Input() headerVisible: boolean;
-    @Input() dashboard: Dashboard;
+  @Input() editMode: boolean;
+  @Input() headerVisible: boolean;
+  @Input() dashboard: Dashboard;
+  @Input() allMeasurements: DataLakeMeasure[];
 
-    @Output() deleteCallback: EventEmitter<DashboardItem> = new EventEmitter<DashboardItem>();
-    @Output() updateCallback: EventEmitter<DashboardWidgetModel> = new EventEmitter<DashboardWidgetModel>();
+  @Output() deleteCallback: EventEmitter<DashboardItem> = new EventEmitter<DashboardItem>();
+  @Output() updateCallback: EventEmitter<DashboardWidgetModel> = new EventEmitter<DashboardWidgetModel>();
 
-    options: DashboardConfig;
-    loaded = false;
+  options: DashboardConfig;
+  loaded = false;
 
-    @ViewChildren(GridsterItemComponent) gridsterItemComponents: QueryList<GridsterItemComponent>;
+  subscription: Subscription;
 
-    constructor(private resizeService: ResizeService) {
+  @ViewChildren(GridsterItemComponent) gridsterItemComponents: QueryList<GridsterItemComponent>;
+  @ViewChildren(DashboardWidgetComponent) dashboardWidgetComponents: QueryList<DashboardWidgetComponent>;
 
+  constructor(private resizeService: ResizeService,
+              private datalakeRestService: DatalakeRestService) {
+
+  }
+
+  ngOnInit(): void {
+    this.options = {
+      disablePushOnDrag: true,
+      draggable: {enabled: this.editMode},
+      gridType: GridType.VerticalFixed,
+      minCols: 12,
+      maxCols: 12,
+      minRows: 4,
+      fixedRowHeight: 50,
+      fixedColWidth: 50,
+      margin: 5,
+      resizable: {enabled: this.editMode},
+      displayGrid: this.editMode ? 'always' : 'none',
+      itemResizeCallback: ((item, itemComponent) => {
+        this.resizeService.notify({
+          gridsterItem: item,
+          gridsterItemComponent: itemComponent
+        } as GridsterInfo);
+      }),
+      itemInitCallback: ((item, itemComponent) => {
+        this.resizeService.notify({
+          gridsterItem: item,
+          gridsterItemComponent: itemComponent
+        } as GridsterInfo);
+        //window.dispatchEvent(new Event('resize'));
+      })
+    };
+  }
+
+  ngOnDestroy() {
+    if (this.subscription) {
+      this.subscription.unsubscribe();
     }
+  }
 
-    ngOnInit(): void {
-        this.options = {
-            disablePushOnDrag: true,
-            draggable: { enabled: this.editMode },
-            gridType: GridType.VerticalFixed,
-            minCols: 12,
-            maxCols: 12,
-            minRows: 4,
-            fixedRowHeight: 50,
-            fixedColWidth: 50,
-            margin: 5,
-            resizable: { enabled: this.editMode },
-            displayGrid: this.editMode ? 'always' : 'none',
-            itemResizeCallback: ((item, itemComponent) => {
-                this.resizeService.notify({id: item.id, width: itemComponent.width, height: itemComponent.height});
-            }),
-            itemInitCallback: ((item, itemComponent) => {
-                this.resizeService.notify({id: item.id, width: itemComponent.width, height: itemComponent.height});
-            })
-        };
+  ngOnChanges(changes: SimpleChanges): void {
+    if (changes['editMode'] && this.options) {
+      this.options.draggable.enabled = this.editMode;
+      this.options.resizable.enabled = this.editMode;
+      this.options.displayGrid = this.editMode ? 'always' : 'none';
+      this.options.api.optionsChanged();
     }
+  }
 
-    ngOnChanges(changes: SimpleChanges): void {
-        if (changes['editMode'] && this.options) {
-            this.options.draggable.enabled = this.editMode;
-            this.options.resizable.enabled = this.editMode;
-            this.options.displayGrid = this.editMode ? 'always' : 'none';
-            this.options.api.optionsChanged();
+  propagateItemRemoval(widget: DashboardItem) {
+    this.deleteCallback.emit(widget);
+  }
+
+  propagateItemUpdate(dashboardWidget: DashboardWidgetModel) {
+    this.updateCallback.emit(dashboardWidget);
+  }
+
+  ngAfterContentInit(): void {
+    if (this.dashboard.dashboardGeneralSettings.globalRefresh) {
+      this.checkWidgetsReady();
+    }
+  }
+
+  checkWidgetsReady() {
+    if (this.dashboardWidgetComponents) {
+      this.createQuerySubscription();
+    } else {
+      setTimeout(() => this.checkWidgetsReady(), 1000);
+    }
+  }
+
+  createQuerySubscription() {
+    this.subscription = timer(0, this.dashboard.dashboardGeneralSettings.refreshIntervalInSeconds * 1000)
+      .pipe(exhaustMap(() => this.makeQueryObservable()))
+      .subscribe(res => {
+        if (res.length > 0) {
+          this.dashboardWidgetComponents.forEach((widget, index) => {
+            const widgetId = widget.getWidgetId();
+            const queryResult = res.find(r => r.forId === widgetId);
+            if (queryResult) {
+              widget.processQueryResponse(queryResult);
+            }
+          });
         }
-    }
+      });
+  }
 
-    propagateItemRemoval(widget: DashboardItem) {
-        this.deleteCallback.emit(widget);
-    }
-
-    propagateItemUpdate(dashboardWidget: DashboardWidgetModel) {
-        this.updateCallback.emit(dashboardWidget);
-    }
-
+  makeQueryObservable(): Observable<SpQueryResult[]> {
+    const queries = this.dashboardWidgetComponents
+      .map(dw => dw.getWidgetQuery())
+      .filter(query => query !== undefined);
+    return this.datalakeRestService.performMultiQuery(queries);
+  }
 }
diff --git a/ui/src/app/dashboard/components/overview/dashboard-overview.component.css b/ui/src/app/dashboard/components/overview/dashboard-overview.component.css
index 121e838..8bd5722 100644
--- a/ui/src/app/dashboard/components/overview/dashboard-overview.component.css
+++ b/ui/src/app/dashboard/components/overview/dashboard-overview.component.css
@@ -36,3 +36,10 @@
     display: inline;
     margin-right: 10px;
 }
+
+.mat-row:nth-child(even) {
+    background-color: var(--color-bg-1);
+}
+.mat-row:nth-child(odd) {
+    background-color: var(--color-bg-2);
+}
diff --git a/ui/src/app/dashboard/components/overview/dashboard-overview.component.html b/ui/src/app/dashboard/components/overview/dashboard-overview.component.html
index d557cd9..054a420 100644
--- a/ui/src/app/dashboard/components/overview/dashboard-overview.component.html
+++ b/ui/src/app/dashboard/components/overview/dashboard-overview.component.html
@@ -16,91 +16,98 @@
   ~
   -->
 
-<div fxFlex="100" fxLayout="column">
-    <div fxFlex="100" fxLayout="column">
-        <div fxLayout="row" class="fixed-height options-bar sp-tab-bg">
-            <div class="options-bar-item pl-10" fxLayoutAlign="start center" fxLayout="row">
-                <button mat-button
-                        mat-raised-button
-                        color="accent"
-                        (click)="openNewDashboardDialog()"
-                        *ngIf="hasDashboardWritePrivileges"
-                        data-cy="new-dashboard-btn">
-                    <i class="material-icons">add</i>
-                    <span> New dashboard</span>
-                </button>
-            </div>
-        </div>
+<sp-basic-view [showBackLink]="false" [padding]="true">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <button mat-button mat-raised-button color="accent"
+                data-cy="new-dashboard-btn"
+                (click)="openNewDashboardDialog()"
+                *ngIf="hasDashboardWritePrivileges">
+            <i class="material-icons">add</i>
+            <span>New Dashboard</span>
+        </button>
     </div>
-    <div fxFlex="100" fxLayout="row wrap" fxLayoutAlign="start stretch" class="m-20">
-        <div fxFlex="100" class="assemblyOptions sp-blue-bg p-5">
-            <div fxLayout="row" fxLayoutAlign="start center" fxFlex="100">
-                <h4>My dashboards</h4>
-                <span fxFlex></span>
-            </div>
-        </div>
-        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="sp-blue-border">
 
-            <table fxFlex="95" mat-table [dataSource]="dataSource" multiTemplateDataRows>
+    <div fxFlex="100" fxLayout="column">
+        <sp-basic-header-title-component title="My Dashboards"></sp-basic-header-title-component>
+        <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+            <sp-basic-inner-panel [showTitle]="false" innerPadding="0" outerMargin="0" fxFlex="90" [hideToolbar]="true">
+                <div fxFlex="100" fxLayout="column" class="w-100" *ngIf="dashboards.length > 0">
 
-                <ng-container matColumnDef="name">
-                    <th fxFlex="60" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Dashboard</th>
-                    <td fxFlex="60" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
-                        {{element.name}}<br/>
-                        {{element.description}}
-                    </td>
-                </ng-container>
+                    <table fxFlex="95" mat-table [dataSource]="dataSource" multiTemplateDataRows>
 
-                <ng-container matColumnDef="actions">
-                    <th fxFlex="40" fxLayoutAlign="center center" mat-header-cell *matHeaderCellDef> Actions</th>
-                    <td fxFlex="40" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
-                        <div fxLayout="row" fxFlex="100">
+                        <ng-container matColumnDef="name">
+                            <th fxFlex="60" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Dashboard
+                            </th>
+                            <td fxFlex="60" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+                                {{element.name}}<br/>
+                                {{element.description}}
+                            </td>
+                        </ng-container>
+
+                        <ng-container matColumnDef="actions">
+                            <th fxFlex="40" fxLayoutAlign="center center" mat-header-cell *matHeaderCellDef> Actions
+                            </th>
+                            <td fxFlex="40" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+                                <div fxLayout="row" fxFlex="100">
                             <span fxFlex fxFlexOrder="1" fxLayout="row" fxLayoutAlign="center center">
                             <button mat-button mat-icon-button color="accent"
-                                    (click)="showDashboard(element, false)"
+                                    (click)="showDashboard(element)"
                                     [attr.data-cy]="'show-dashboard-' + element.name">
                                 <i class="material-icons">visibility</i>
                             </button>
                             </span>
-                            <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center">
+                                    <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center">
                             <button mat-button mat-icon-button color="accent"
                                     (click)="openExternalDashboard(element)">
                                 <i class="material-icons">open_in_new</i>
                             </button>
                             </span>
-                            <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center" *ngIf="hasDashboardWritePrivileges">
+                                    <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center"
+                                          *ngIf="hasDashboardWritePrivileges">
                             <button mat-button mat-icon-button color="accent"
                                     (click)="openEditDashboardDialog(element)">
                                 <i class="material-icons">settings</i>
                             </button>
                             </span>
-                            <span fxFlex fxFlexOrder="4" fxLayout="row" fxLayoutAlign="center center" *ngIf="hasDashboardWritePrivileges">
+                                    <span fxFlex fxFlexOrder="4" fxLayout="row" fxLayoutAlign="center center"
+                                          *ngIf="hasDashboardWritePrivileges">
                             <button mat-button mat-icon-button color="accent"
-                                    (click)="showDashboard(element, true)"
+                                    (click)="editDashboard(element)"
                                     [attr.data-cy]="'edit-dashboard-' + element.name">
                                 <i class="material-icons">edit</i>
                             </button>
                             </span>
-                            <span fxFlex fxFlexOrder="5" fxLayout="row" fxLayoutAlign="center center" *ngIf="isAdmin">
+                                    <span fxFlex fxFlexOrder="5" fxLayout="row" fxLayoutAlign="center center"
+                                          *ngIf="isAdmin">
                             <button mat-button mat-icon-button color="accent"
                                     (click)="showPermissionsDialog(element)">
                                 <i class="material-icons">share</i>
                             </button>
                             </span>
-                            <span fxFlex fxFlexOrder="6" fxLayout="row" fxLayoutAlign="center center" *ngIf="hasDashboardDeletePrivileges">
+                                    <span fxFlex fxFlexOrder="6" fxLayout="row" fxLayoutAlign="center center"
+                                          *ngIf="hasDashboardDeletePrivileges">
                             <button mat-button mat-icon-button color="accent"
                                     (click)="openDeleteDashboardDialog(element)">
                                 <i class="material-icons">delete</i>
                             </button>
                             </span>
-                        </div>
-                    </td>
-                </ng-container>
+                                </div>
+                            </td>
+                        </ng-container>
 
-                <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
-                <tr mat-row *matRowDef="let element; columns: displayedColumns;">
-                </tr>
-            </table>
+                        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                        <tr mat-row *matRowDef="let element; columns: displayedColumns;">
+                        </tr>
+                    </table>
+                </div>
+                <div fxFlex="100"
+                     fxLayout="column"
+                     fxLayoutAlign="center center"
+                     *ngIf="dashboards.length == 0">
+                    <h5>(no dashboards available)</h5>
+                </div>
+            </sp-basic-inner-panel>
         </div>
     </div>
-</div>
+</sp-basic-view>
diff --git a/ui/src/app/dashboard/components/overview/dashboard-overview.component.ts b/ui/src/app/dashboard/components/overview/dashboard-overview.component.ts
index 86387fc..3d41f70 100644
--- a/ui/src/app/dashboard/components/overview/dashboard-overview.component.ts
+++ b/ui/src/app/dashboard/components/overview/dashboard-overview.component.ts
@@ -16,19 +16,19 @@
  *
  */
 
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { Dashboard } from '@streampipes/platform-services';
+import { Component, OnInit } from '@angular/core';
+import { Dashboard, DashboardService } from '@streampipes/platform-services';
 import { MatTableDataSource } from '@angular/material/table';
 import { MatDialog } from '@angular/material/dialog';
-import { DashboardService } from '../../services/dashboard.service';
 import { EditDashboardDialogComponent } from '../../dialogs/edit-dashboard/edit-dashboard-dialog.component';
-import { Tuple2 } from '../../../core-model/base/Tuple2';
 import { Router } from '@angular/router';
 import { ObjectPermissionDialogComponent } from '../../../core-ui/object-permission-dialog/object-permission-dialog.component';
-import { PanelType, DialogService } from '@streampipes/shared-ui';
+import { DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
 import { UserRole } from '../../../_enums/user-role.enum';
 import { AuthService } from '../../../services/auth.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
+import { SpDashboardRoutes } from '../../dashboard.routes';
+import { zip } from 'rxjs';
 
 @Component({
   selector: 'dashboard-overview',
@@ -37,9 +37,7 @@
 })
 export class DashboardOverviewComponent implements OnInit {
 
-  @Input() dashboards: Dashboard[];
-  @Output() reloadDashboardsEmitter = new EventEmitter<void>();
-  @Output() selectDashboardEmitter = new EventEmitter<Tuple2<Dashboard, boolean>>();
+  dashboards: Dashboard[] = [];
 
   dataSource = new MatTableDataSource<Dashboard>();
   displayedColumns: string[] = [];
@@ -52,11 +50,13 @@
               public dialog: MatDialog,
               private router: Router,
               private dialogService: DialogService,
-              private authService: AuthService) {
+              private authService: AuthService,
+              private breadcrumbService: SpBreadcrumbService) {
 
   }
 
   ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpDashboardRoutes.BASE));
     this.authService.user$.subscribe(user => {
       this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
       this.hasDashboardWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_DASHBOARD);
@@ -64,12 +64,20 @@
       this.displayedColumns = ['name', 'actions'];
 
     });
-    this.dataSource.data = this.dashboards;
+    this.getDashboards();
+  }
+
+  getDashboards() {
+    this.dashboardService.getDashboards().subscribe(data => {
+      this.dashboards = data.sort((a, b) => a.name.localeCompare(b.name));
+      this.dataSource.data = this.dashboards;
+    });
   }
 
   openNewDashboardDialog() {
     const dashboard = {} as Dashboard;
     dashboard.widgets = [];
+    dashboard.dashboardGeneralSettings = {};
 
     this.openDashboardModificationDialog(true, dashboard);
   }
@@ -86,7 +94,7 @@
     });
 
     dialogRef.afterClosed().subscribe(result => {
-      this.reloadDashboardsEmitter.emit();
+      this.getDashboards();
     });
   }
 
@@ -96,16 +104,18 @@
 
   openDeleteDashboardDialog(dashboard: Dashboard) {
     // TODO add confirm dialog
-    this.dashboardService.deleteDashboard(dashboard).subscribe(result => {
-      this.reloadDashboardsEmitter.emit();
+    const widgetsToDelete = dashboard.widgets.map(widget => this.dashboardService.deleteWidget(widget.id));
+    zip(...widgetsToDelete, this.dashboardService.deleteDashboard(dashboard)).subscribe(result => {
+      this.getDashboards();
     });
   }
 
-  showDashboard(dashboard: Dashboard, openInEditMode: boolean) {
-    const data: Tuple2<Dashboard, boolean> = {} as Tuple2<Dashboard, boolean>;
-    data.a = dashboard;
-    data.b = openInEditMode;
-    this.selectDashboardEmitter.emit(data);
+  showDashboard(dashboard: Dashboard): void {
+    this.router.navigate(['dashboard', dashboard._id]);
+  }
+
+  editDashboard(dashboard: Dashboard): void {
+    this.router.navigate(['dashboard', dashboard._id], {queryParams: {action: 'edit'}});
   }
 
   openExternalDashboard(dashboard: Dashboard) {
@@ -128,7 +138,7 @@
 
     dialogRef.afterClosed().subscribe(refresh => {
       if (refresh) {
-        this.reloadDashboardsEmitter.emit();
+        this.getDashboards();
       }
     });
   }
diff --git a/ui/src/app/dashboard/components/panel/dashboard-panel.component.html b/ui/src/app/dashboard/components/panel/dashboard-panel.component.html
index 9f1fe82..1e368cf 100644
--- a/ui/src/app/dashboard/components/panel/dashboard-panel.component.html
+++ b/ui/src/app/dashboard/components/panel/dashboard-panel.component.html
@@ -15,9 +15,11 @@
   ~ limitations under the License.
   ~
   -->
-<div fxFlex="100" fxLayout="column">
-    <div fxLayout="row" class="fixed-height options-bar sp-tab-bg" *ngIf="editMode">
-        <div class="options-bar-item pl-10" fxLayoutAlign="start center" fxLayout="row">
+
+<sp-basic-view [showBackLink]="true" [padding]="false" [backLinkTarget]="['dashboard']">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <div fxLayout="row" fxFlex="100" *ngIf="editMode" fxLayoutAlign="start center">
             <button mat-button
                     mat-raised-button
                     color="accent"
@@ -43,9 +45,7 @@
                 <i class="material-icons">add</i>
                 <span> Add visualization</span>
             </button>
-        </div>
-        <span fxFlex></span>
-        <div class="options-bar-item" fxLayoutAlign="start center" fxLayout="row" >
+            <span fxFlex></span>
             <mat-slide-toggle
                     color="accent"
                     [(ngModel)]="headerVisible">
@@ -53,11 +53,13 @@
             </mat-slide-toggle>
         </div>
     </div>
-
-    <dashboard-grid [editMode]="editMode" [dashboard]="dashboard"
-                    [headerVisible]="headerVisible"
-                    (updateCallback)="updateAndQueueItemForDeletion($event)"
-                    (deleteCallback)="removeAndQueueItemForDeletion($event)"
-                    class="h-100 dashboard-grid"></dashboard-grid>
-</div>
-
+    <div fxFlex="100" fxLayout="column">
+        <dashboard-grid [editMode]="editMode" [dashboard]="dashboard"
+                        [headerVisible]="headerVisible"
+                        [allMeasurements]="allMeasurements"
+                        (updateCallback)="updateAndQueueItemForDeletion($event)"
+                        (deleteCallback)="removeAndQueueItemForDeletion($event)"
+                        *ngIf="dashboard && allMeasurements"
+                        class="h-100 dashboard-grid"></dashboard-grid>
+    </div>
+</sp-basic-view>
diff --git a/ui/src/app/dashboard/components/panel/dashboard-panel.component.ts b/ui/src/app/dashboard/components/panel/dashboard-panel.component.ts
index 4ca676d..11d0cfb 100644
--- a/ui/src/app/dashboard/components/panel/dashboard-panel.component.ts
+++ b/ui/src/app/dashboard/components/panel/dashboard-panel.component.ts
@@ -16,13 +16,25 @@
  *
  */
 
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { Dashboard, ClientDashboardItem, DashboardWidgetModel } from '@streampipes/platform-services';
-import { forkJoin, Observable, Subscription } from 'rxjs';
+import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import {
+    ClientDashboardItem,
+    Dashboard,
+    DashboardService,
+    DashboardWidgetModel, DataLakeMeasure,
+    DatalakeRestService
+} from '@streampipes/platform-services';
+import { forkJoin, Observable, of, Subscription } from 'rxjs';
 import { AddVisualizationDialogComponent } from '../../dialogs/add-widget/add-visualization-dialog.component';
-import { DashboardService } from '../../services/dashboard.service';
 import { RefreshDashboardService } from '../../services/refresh-dashboard.service';
-import { PanelType, DialogService } from '@streampipes/shared-ui';
+import { ConfirmDialogComponent, DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
+import { ActivatedRoute, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
+import { UserPrivilege } from '../../../_enums/user-privilege.enum';
+import { AuthService } from '../../../services/auth.service';
+import { SpDashboardRoutes } from '../../dashboard.routes';
+import { map } from 'rxjs/operators';
+import { MatDialog } from '@angular/material/dialog';
+
 @Component({
     selector: 'dashboard-panel',
     templateUrl: './dashboard-panel.component.html',
@@ -30,8 +42,8 @@
 })
 export class DashboardPanelComponent implements OnInit {
 
-    @Input() dashboard: Dashboard;
-    @Input('editMode') editMode: boolean;
+    dashboard: Dashboard;
+    editMode: boolean;
     @Output('editModeChange') editModeChange: EventEmitter<boolean> = new EventEmitter();
 
     public items: ClientDashboardItem[];
@@ -40,16 +52,49 @@
 
     widgetIdsToRemove: string[] = [];
     widgetsToUpdate: Map<string, DashboardWidgetModel> = new Map<string, DashboardWidgetModel>();
+    allMeasurements: DataLakeMeasure[];
 
     headerVisible = true;
 
     constructor(private dashboardService: DashboardService,
+                private datalakeRestService: DatalakeRestService,
                 private dialogService: DialogService,
-                private refreshDashboardService: RefreshDashboardService) {
+                private dialog: MatDialog,
+                private refreshDashboardService: RefreshDashboardService,
+                private route: ActivatedRoute,
+                private authService: AuthService,
+                private breadcrumbService: SpBreadcrumbService) {
     }
 
     public ngOnInit() {
+        const params = this.route.snapshot.params;
+        const queryParams = this.route.snapshot.queryParams;
 
+        this.authService.user$.subscribe(user => {
+             const hasDashboardWritePrivileges = this.authService.hasRole(
+              UserPrivilege.PRIVILEGE_WRITE_DASHBOARD
+            );
+            if (queryParams.action === 'edit' && hasDashboardWritePrivileges) {
+                this.editMode = true;
+            }
+        });
+
+        this.getDashboard(params.id);
+        this.getAllMeasurements();
+
+    }
+
+    getDashboard(dashboardId: string): void {
+        this.dashboardService.getDashboard(dashboardId).subscribe(dashboard => {
+            if (dashboard) {
+                this.dashboard = dashboard;
+                this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.makeRoute([SpDashboardRoutes.BASE], this.dashboard.name));
+            }
+        });
+    }
+
+    getAllMeasurements(): void {
+        this.datalakeRestService.getAllMeasurementSeries().subscribe(res => this.allMeasurements = res);
     }
 
     addWidget(): void {
@@ -93,8 +138,8 @@
     }
 
     closeEditModeAndReloadDashboard() {
-        this.editModeChange.emit(!(this.editMode));
-        this.refreshDashboardService.notify(this.dashboard._id);
+        this.editMode = !this.editMode;
+        this.getDashboard(this.dashboard._id);
     }
 
     prepareWidgetUpdates(): Observable<any>[] {
@@ -125,4 +170,28 @@
             this.dashboardService.deleteWidget(widgetId).subscribe();
         });
     }
+
+    confirmLeaveDashboard(route: ActivatedRouteSnapshot,
+                          state: RouterStateSnapshot): Observable<boolean> {
+        if (this.editMode) {
+            const dialogRef = this.dialog.open(ConfirmDialogComponent, {
+                width: '500px',
+                data: {
+                    'title': 'Save changes?',
+                    'subtitle': 'Update all changes to dashboard widgets or discard current changes.',
+                    'cancelTitle': 'Discard changes',
+                    'okTitle': 'Update',
+                    'confirmAndCancel': true
+                },
+            });
+            return dialogRef.afterClosed().pipe(map(shouldUpdate => {
+                if (shouldUpdate) {
+                    this.updateDashboardAndCloseEditMode();
+                }
+                return true;
+            }));
+        } else {
+            return of(true);
+        }
+    }
 }
diff --git a/ui/src/app/dashboard/components/standalone/standalone-dashboard.component.html b/ui/src/app/dashboard/components/standalone/standalone-dashboard.component.html
index a5e7832..1103c2b 100644
--- a/ui/src/app/dashboard/components/standalone/standalone-dashboard.component.html
+++ b/ui/src/app/dashboard/components/standalone/standalone-dashboard.component.html
@@ -17,5 +17,5 @@
 <div fxFlex="100" class="panel">
 <dashboard-grid [editMode]="false" [dashboard]="dashboard"
                 class="h-100" *ngIf="dashboardReady"></dashboard-grid>
-    <img src="/assets/img/favicon/apple-touch-icon-76x76.png" class="icon-overlay">
-</div>
\ No newline at end of file
+    <img src="/assets/img/favicon/favicon-96x96.png" class="icon-overlay">
+</div>
diff --git a/ui/src/app/dashboard/components/standalone/standalone-dashboard.component.ts b/ui/src/app/dashboard/components/standalone/standalone-dashboard.component.ts
index ca41c44..03b3d1f 100644
--- a/ui/src/app/dashboard/components/standalone/standalone-dashboard.component.ts
+++ b/ui/src/app/dashboard/components/standalone/standalone-dashboard.component.ts
@@ -16,8 +16,7 @@
  */
 
 import { Component, OnInit } from '@angular/core';
-import { Dashboard } from '@streampipes/platform-services';
-import { DashboardService } from '../../services/dashboard.service';
+import { Dashboard, DashboardService } from '@streampipes/platform-services';
 import { ActivatedRoute } from '@angular/router';
 
 @Component({
@@ -37,7 +36,6 @@
         this.activatedRoute.params.subscribe(params => {
             if (params['dashboardId']) {
                 const dashboardId = params['dashboardId'];
-                console.log(dashboardId);
                 this.dashboardService.getDashboard(dashboardId).subscribe(dashboard => {
                     this.dashboard = dashboard;
                     this.dashboardReady = true;
diff --git a/ui/src/app/dashboard/components/widget/dashboard-widget.component.html b/ui/src/app/dashboard/components/widget/dashboard-widget.component.html
index 1c4e872..d7a4ec7 100644
--- a/ui/src/app/dashboard/components/widget/dashboard-widget.component.html
+++ b/ui/src/app/dashboard/components/widget/dashboard-widget.component.html
@@ -51,100 +51,128 @@
             </div>
             <div *ngIf="widgetLoaded && pipelineRunning" class="h-100">
                 <div *ngIf="configuredWidget.widgetType === 'number'" class="h-100 p-0">
-                    <number-widget [itemWidth]="itemWidth"
+                    <number-widget [itemWidth]="itemWidth" #activeWidget
                                    [itemHeight]="itemHeight"
                                    [editMode]="editMode"
+                                   [globalRefresh]="globalRefresh"
+                                   [gridsterItemComponent]="gridsterItemComponent"
                                    [widgetConfig]="configuredWidget" [widgetDataConfig]="widgetDataConfig"
                                    class="h-100"></number-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'line'" class="h-100 p-0">
-                    <line-widget [itemWidth]="itemWidth"
+                    <line-widget [itemWidth]="itemWidth" #activeWidget
                                  [itemHeight]="itemHeight"
                                  [editMode]="editMode"
+                                 [globalRefresh]="globalRefresh"
+                                 [gridsterItemComponent]="gridsterItemComponent"
                                  [widgetConfig]="configuredWidget"
                                  [widgetDataConfig]="widgetDataConfig" class="h-100"></line-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'area'" class="h-100 p-0">
-                    <area-widget [itemWidth]="itemWidth"
+                    <area-widget [itemWidth]="itemWidth" #activeWidget
                                  [itemHeight]="itemHeight"
                                  [editMode]="editMode"
+                                 [globalRefresh]="globalRefresh"
+                                 [gridsterItemComponent]="gridsterItemComponent"
                                  [widgetConfig]="configuredWidget"
                                  [widgetDataConfig]="widgetDataConfig" class="h-100"></area-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'table'" class="h-100 p-0">
-                    <table-widget [itemWidth]="itemWidth"
+                    <table-widget [itemWidth]="itemWidth" #activeWidget
                                   [itemHeight]="itemHeight"
                                   [editMode]="editMode"
+                                  [globalRefresh]="globalRefresh"
+                                  [gridsterItemComponent]="gridsterItemComponent"
                                   [widgetConfig]="configuredWidget"
                                   [widgetDataConfig]="widgetDataConfig" class="h-100"></table-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'gauge'" class="h-100 p-0">
-                    <gauge-widget [itemWidth]="itemWidth"
+                    <gauge-widget [itemWidth]="itemWidth" #activeWidget
                                   [itemHeight]="itemHeight"
                                   [editMode]="editMode"
+                                  [globalRefresh]="globalRefresh"
+                                  [gridsterItemComponent]="gridsterItemComponent"
                                   [widgetConfig]="configuredWidget"
                                   [widgetDataConfig]="widgetDataConfig" class="h-100"></gauge-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'image'" class="h-100 p-0">
-                    <image-widget [itemWidth]="itemWidth"
+                    <image-widget [itemWidth]="itemWidth" #activeWidget
                                   [itemHeight]="itemHeight"
                                   [editMode]="editMode"
+                                  [globalRefresh]="globalRefresh"
+                                  [gridsterItemComponent]="gridsterItemComponent"
                                   [widgetConfig]="configuredWidget"
                                   [widgetDataConfig]="widgetDataConfig" class="h-100"></image-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'map'" class="h-100 p-0">
-                    <map-widget [itemWidth]="itemWidth"
+                    <map-widget [itemWidth]="itemWidth" #activeWidget
                                 [itemHeight]="itemHeight"
                                 [editMode]="editMode"
+                                [globalRefresh]="globalRefresh"
+                                [gridsterItemComponent]="gridsterItemComponent"
                                 [widgetConfig]="configuredWidget"
                                 [widgetDataConfig]="widgetDataConfig" class="h-100"></map-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'raw'" class="h-100 p-0">
-                    <raw-widget [itemWidth]="itemWidth"
+                    <raw-widget [itemWidth]="itemWidth" #activeWidget
                                 [itemHeight]="itemHeight"
                                 [editMode]="editMode"
+                                [globalRefresh]="globalRefresh"
+                                [gridsterItemComponent]="gridsterItemComponent"
                                 [widgetConfig]="configuredWidget"
                                 [widgetDataConfig]="widgetDataConfig" class="h-100"></raw-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'html'" class="h-100 p-0">
-                    <html-widget [itemWidth]="itemWidth"
+                    <html-widget [itemWidth]="itemWidth" #activeWidget
                                  [itemHeight]="itemHeight"
                                  [editMode]="editMode"
+                                 [globalRefresh]="globalRefresh"
+                                 [gridsterItemComponent]="gridsterItemComponent"
                                  [widgetConfig]="configuredWidget"
                                  [widgetDataConfig]="widgetDataConfig" class="h-100"></html-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'trafficlight'" class="h-100 p-0">
-                    <traffic-light-widget [itemWidth]="itemWidth"
+                    <traffic-light-widget [itemWidth]="itemWidth" #activeWidget
                                           [itemHeight]="itemHeight"
                                           [editMode]="editMode"
+                                          [globalRefresh]="globalRefresh"
+                                          [gridsterItemComponent]="gridsterItemComponent"
                                           [widgetConfig]="configuredWidget"
                                           [widgetDataConfig]="widgetDataConfig" class="h-100"></traffic-light-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'wordcloud'" class="h-100 p-0">
-                    <wordcloud-widget [itemWidth]="itemWidth"
+                    <wordcloud-widget [itemWidth]="itemWidth" #activeWidget
                                       [itemHeight]="itemHeight"
                                       [editMode]="editMode"
+                                      [globalRefresh]="globalRefresh"
+                                      [gridsterItemComponent]="gridsterItemComponent"
                                       [widgetConfig]="configuredWidget"
                                       [widgetDataConfig]="widgetDataConfig" class="h-100"></wordcloud-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'status'" class="h-100 p-0">
-                    <status-widget [itemWidth]="itemWidth"
+                    <status-widget [itemWidth]="itemWidth" #activeWidget
                                    [itemHeight]="itemHeight"
                                    [editMode]="editMode"
+                                   [globalRefresh]="globalRefresh"
+                                   [gridsterItemComponent]="gridsterItemComponent"
                                    [widgetConfig]="configuredWidget"
                                    [widgetDataConfig]="widgetDataConfig" class="h-100"></status-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'bar-race'" class="h-100 p-0">
-                    <bar-race-widget [itemWidth]="itemWidth"
+                    <bar-race-widget [itemWidth]="itemWidth" #activeWidget
                                      [itemHeight]="itemHeight"
                                      [editMode]="editMode"
+                                     [globalRefresh]="globalRefresh"
+                                     [gridsterItemComponent]="gridsterItemComponent"
                                      [widgetConfig]="configuredWidget"
                                      [widgetDataConfig]="widgetDataConfig" class="h-100"></bar-race-widget>
                 </div>
                 <div *ngIf="configuredWidget.widgetType === 'stacked-line-chart'" class="h-100 p-0">
-                    <stacked-line-chart-widget [itemWidth]="itemWidth"
+                    <stacked-line-chart-widget [itemWidth]="itemWidth" #activeWidget
                                                [itemHeight]="itemHeight"
                                                [editMode]="editMode"
+                                               [globalRefresh]="globalRefresh"
+                                               [gridsterItemComponent]="gridsterItemComponent"
                                                [widgetConfig]="configuredWidget"
                                                [widgetDataConfig]="widgetDataConfig"
                                                class="h-100"></stacked-line-chart-widget>
diff --git a/ui/src/app/dashboard/components/widget/dashboard-widget.component.ts b/ui/src/app/dashboard/components/widget/dashboard-widget.component.ts
index 35213ac..85b12ec 100644
--- a/ui/src/app/dashboard/components/widget/dashboard-widget.component.ts
+++ b/ui/src/app/dashboard/components/widget/dashboard-widget.component.ts
@@ -16,21 +16,36 @@
  *
  */
 
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { DashboardService } from '../../services/dashboard.service';
+import {
+  Component,
+  EventEmitter,
+  Input,
+  OnInit,
+  Output,
+  QueryList, ViewChild,
+  ViewChildren,
+  ViewContainerRef
+} from '@angular/core';
 import { AddVisualizationDialogComponent } from '../../dialogs/add-widget/add-visualization-dialog.component';
 import {
   DashboardItem,
+  DashboardService,
   DashboardWidgetModel,
-  DataLakeMeasure, DatalakeRestService,
+  DataLakeMeasure, DatalakeQueryParameters,
+  DatalakeRestService,
   DataViewDataExplorerService,
   Pipeline,
-  PipelineService
+  PipelineService, SpQueryResult
 } from '@streampipes/platform-services';
 import { DialogService, PanelType } from '@streampipes/shared-ui';
 import { EditModeService } from '../../services/edit-mode.service';
 import { ReloadPipelineService } from '../../services/reload-pipeline.service';
 import { zip } from 'rxjs';
+import { GridsterItemComponent } from 'angular-gridster2';
+import { ResizeService } from '../../services/resize.service';
+import { GridsterInfo } from '../../models/gridster-info.model';
+import { BaseDataExplorerWidgetDirective } from '../../../data-explorer/components/widgets/base/base-data-explorer-widget.directive';
+import { BaseStreamPipesWidget } from '../widgets/base/base-widget';
 
 @Component({
   selector: 'dashboard-widget',
@@ -44,6 +59,9 @@
   @Input() headerVisible = false;
   @Input() itemWidth: number;
   @Input() itemHeight: number;
+  @Input() gridsterItemComponent: GridsterItemComponent;
+  @Input() globalRefresh: boolean;
+  @Input() allMeasurements: DataLakeMeasure[];
 
   @Output() deleteCallback: EventEmitter<DashboardItem> = new EventEmitter<DashboardItem>();
   @Output() updateCallback: EventEmitter<DashboardWidgetModel> = new EventEmitter<DashboardWidgetModel>();
@@ -56,13 +74,16 @@
   pipelineRunning = false;
   widgetNotAvailable = false;
 
+  _activeWidget: BaseStreamPipesWidget;
+
   constructor(private dashboardService: DashboardService,
               private dialogService: DialogService,
               private pipelineService: PipelineService,
               private editModeService: EditModeService,
               private reloadPipelineService: ReloadPipelineService,
               private dataExplorerService: DataViewDataExplorerService,
-              private dataLakeRestService: DatalakeRestService) {
+              private dataLakeRestService: DatalakeRestService,
+              private resizeService: ResizeService) {
   }
 
   ngOnInit(): void {
@@ -80,22 +101,28 @@
   }
 
   loadVisualizablePipeline() {
-    zip(this.dataExplorerService.getPersistedDataStream(this.configuredWidget.pipelineId, this.configuredWidget.visualizationName), this.dataLakeRestService.getAllMeasurementSeries())
+    zip(this.dataExplorerService.getPersistedDataStream(this.configuredWidget.pipelineId, this.configuredWidget.visualizationName))
       .subscribe(res => {
         const vizPipeline = res[0];
-        const measurement = res[1].find(m => m.measureName === vizPipeline.measureName);
+        const measurement = this.allMeasurements.find(m => m.measureName === vizPipeline.measureName);
         vizPipeline.eventSchema = measurement.eventSchema;
-      this.widgetDataConfig = vizPipeline;
-      this.dashboardService.getPipelineById(vizPipeline.pipelineId).subscribe(pipeline => {
-        this.pipeline = pipeline;
-        this.pipelineRunning = pipeline.running;
-        this.widgetNotAvailable = false;
+        this.widgetDataConfig = vizPipeline;
+        this.dashboardService.getPipelineById(vizPipeline.pipelineId).subscribe(pipeline => {
+          this.pipeline = pipeline;
+          this.pipelineRunning = pipeline.running;
+          this.widgetNotAvailable = false;
+          this.widgetLoaded = true;
+          setTimeout(() => {
+            this.resizeService.notify({
+              gridsterItem: this.widget,
+              gridsterItemComponent: this.gridsterItemComponent
+            } as GridsterInfo);
+          }, 20);
+        });
+      }, err => {
         this.widgetLoaded = true;
+        this.widgetNotAvailable = true;
       });
-    }, err => {
-      this.widgetLoaded = true;
-      this.widgetNotAvailable = true;
-    });
   }
 
   removeWidget() {
@@ -105,11 +132,11 @@
   startPipeline() {
     if (!this.pipelineRunning) {
       this.pipelineService
-          .startPipeline(this.pipeline._id)
-          .subscribe(status => {
-            // this.loadWidget();
-            this.reloadPipelineService.reloadPipelineSubject.next();
-          });
+        .startPipeline(this.pipeline._id)
+        .subscribe(status => {
+          // this.loadWidget();
+          this.reloadPipelineService.reloadPipelineSubject.next();
+        });
     }
   }
 
@@ -139,4 +166,25 @@
       }
     });
   }
+
+  @ViewChild('activeWidget')
+  set activeWidget(activeWidget: BaseStreamPipesWidget) {
+    this._activeWidget = activeWidget;
+  }
+
+  getWidgetQuery(): DatalakeQueryParameters {
+    if (this._activeWidget) {
+      return this._activeWidget.buildQuery(true);
+    } else {
+      return undefined;
+    }
+  }
+
+  processQueryResponse(res: SpQueryResult) {
+    this._activeWidget.processQueryResult(res);
+  }
+
+  getWidgetId(): string {
+    return this.widget.id;
+  }
 }
diff --git a/ui/src/app/dashboard/components/widgets/area/area-widget.component.ts b/ui/src/app/dashboard/components/widgets/area/area-widget.component.ts
index 1e7ea9d..5331ea6 100644
--- a/ui/src/app/dashboard/components/widgets/area/area-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/area/area-widget.component.ts
@@ -39,5 +39,4 @@
     ngOnDestroy(): void {
         super.ngOnDestroy();
     }
-
 }
diff --git a/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.html b/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.html
index d4cf255..59b7f59 100644
--- a/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.html
+++ b/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.html
@@ -20,9 +20,9 @@
     <div class="title-panel mt-20" *ngIf="hasTitlePanelSettings">
         {{selectedTitle}}
     </div>
-    <div class="value-panel">
-        <div echarts [options]="chartOption" [ngStyle]="{'width': '100%', 'height': currentHeight}"
-             (chartInit)="onChartInit($event)" [merge]= "dynamicData" *ngIf="configReady">
+    <div fxFlex [ngStyle]="{height: currentHeight + 'px'}" *ngIf="configReady">
+        <div echarts [options]="chartOption" [ngStyle]="{'width': '100%', 'height': '100%'}"
+             (chartInit)="onChartInit($event)" [merge]= "dynamicData">
         </div>
     </div>
 </div>
diff --git a/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.scss b/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.scss
index 76e1caf..e374f5d 100644
--- a/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.scss
+++ b/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.scss
@@ -30,15 +30,6 @@
   font-size: 20px;
 }
 
-.value-panel {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  align-content: center;
-  flex: 1;
-}
-
 .status-light {
   border-radius: 50%;
   float: left;
diff --git a/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.ts b/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.ts
index 5bbcf60..fa91d9e 100644
--- a/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/bar-race/bar-race-widget.component.ts
@@ -46,10 +46,10 @@
 
   chartOption = {
     grid: {
+      left: 100,
       top: 10,
-      bottom: 30,
-      left: 150,
-      right: 80
+      right: 120,
+      bottom: 100
     },
     xAxis: {
       max: 'dataMax',
@@ -165,4 +165,8 @@
   protected getQueryLimit(extractor: StaticPropertyExtractor): number {
     return 1;
   }
+
+  getFieldsToQuery(): string[] {
+    return [this.partitionField, this.valueField];
+  }
 }
diff --git a/ui/src/app/dashboard/components/widgets/base/base-echarts-widget.ts b/ui/src/app/dashboard/components/widgets/base/base-echarts-widget.ts
index ff37734..2d4e602 100644
--- a/ui/src/app/dashboard/components/widgets/base/base-echarts-widget.ts
+++ b/ui/src/app/dashboard/components/widgets/base/base-echarts-widget.ts
@@ -41,18 +41,12 @@
     this.currentWidth = width;
     this.currentHeight = height;
     this.configReady = true;
-    this.applySize(width, height);
-  }
-
-  onChartInit(ec) {
-    this.eChartsInstance = ec;
-    this.applySize(this.currentWidth, this.currentHeight);
-  }
-
-  applySize(width: number, height: number) {
     if (this.eChartsInstance) {
       this.eChartsInstance.resize({width, height});
     }
   }
 
+  onChartInit(ec) {
+    this.eChartsInstance = ec;
+  }
 }
diff --git a/ui/src/app/dashboard/components/widgets/base/base-ngx-line-charts-widget.ts b/ui/src/app/dashboard/components/widgets/base/base-ngx-line-charts-widget.ts
index 94fef22..64f984c 100644
--- a/ui/src/app/dashboard/components/widgets/base/base-ngx-line-charts-widget.ts
+++ b/ui/src/app/dashboard/components/widgets/base/base-ngx-line-charts-widget.ts
@@ -63,11 +63,16 @@
     }
 
     timestampTickFormatting(timestamp: any): string {
+        const padL = (nr, len = 2, chr = `0`) => `${nr}`.padStart(2, chr);
         const date = new Date(timestamp);
-        return date.getHours() + ':' + date.getMinutes().toString().substr(-2) + ':' + date.getSeconds().toString().substr(-2);
+        return date.getHours() + ':' + `${padL(date.getMinutes())}` + ':' + `${padL(date.getSeconds())}`;
     }
 
     protected getQueryLimit(extractor: StaticPropertyExtractor): number {
         return extractor.integerParameter(WidgetConfigBuilder.QUERY_LIMIT_KEY);
     }
+
+    getFieldsToQuery(): string[] {
+        return [this.selectedNumberProperty];
+    }
 }
diff --git a/ui/src/app/dashboard/components/widgets/base/base-widget.ts b/ui/src/app/dashboard/components/widgets/base/base-widget.ts
index 33ee18a..9a801a4 100644
--- a/ui/src/app/dashboard/components/widgets/base/base-widget.ts
+++ b/ui/src/app/dashboard/components/widgets/base/base-widget.ts
@@ -16,23 +16,24 @@
  *
  */
 
-import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { Directive, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
 import { StaticPropertyExtractor } from '../../../sdk/extractor/static-property-extractor';
-import { BehaviorSubject, interval, Observable, Subscription } from 'rxjs';
+import { BehaviorSubject, interval, Observable, Subscription, timer } from 'rxjs';
 import { WidgetConfigBuilder } from '../../../registry/widget-config-builder';
 import { ResizeService } from '../../../services/resize.service';
-import { WidgetInfo } from '../../../models/gridster-info.model';
 import {
   DashboardWidgetModel,
   DataLakeMeasure,
-  DatalakeQueryParameterBuilder,
-  DatalakeRestService,
+  DatalakeQueryParameterBuilder, DatalakeQueryParameters,
+  DatalakeRestService, EventPropertyPrimitive, EventPropertyUnion, FieldConfig,
   SpQueryResult
 } from '@streampipes/platform-services';
-import { map, switchMap } from 'rxjs/operators';
+import { exhaustMap, map, switchMap } from 'rxjs/operators';
+import { GridsterItemComponent } from 'angular-gridster2';
+import { query } from '@angular/animations';
 
 @Directive()
-export abstract class BaseStreamPipesWidget implements OnChanges {
+export abstract class BaseStreamPipesWidget implements OnInit, OnChanges, OnDestroy {
 
   protected constructor(protected dataLakeService: DatalakeRestService,
                         protected resizeService: ResizeService,
@@ -45,9 +46,11 @@
 
   @Input() widgetConfig: DashboardWidgetModel;
   @Input() widgetDataConfig: DataLakeMeasure;
+  @Input() gridsterItemComponent: GridsterItemComponent;
   @Input() itemWidth: number;
   @Input() itemHeight: number;
   @Input() editMode: boolean;
+  @Input() globalRefresh: boolean;
 
   subscription: Subscription;
   intervalSubject: BehaviorSubject<number>;
@@ -67,22 +70,31 @@
   refreshIntervalInSeconds = 5;
   queryLimit = 1;
 
+  resizeSub: Subscription;
+
   ngOnInit(): void {
-    this.prepareConfigExtraction();
-    this.resizeService.resizeSubject.subscribe(info => {
-      this.onResize(info);
+    const widthOffset = 0;
+    const heightOffset = 0;
+    this.resizeSub = this.resizeService.resizeSubject.subscribe(info => {
+      if (info.gridsterItem.id === this.widgetConfig._id) {
+        this.onSizeChanged(this.computeCurrentWidth(this.gridsterItemComponent.width - widthOffset),
+          this.computeCurrentHeight(this.gridsterItemComponent.height - heightOffset));
+      }
     });
 
-    this.fireQuery().subscribe(result => this.processQueryResult(result));
+    this.prepareConfigExtraction();
 
-    this.intervalSubject = new BehaviorSubject<number>(this.refreshIntervalInSeconds);
-    this.subscription = this.intervalSubject.pipe(
-      switchMap(val => interval(val * 1000)))
-      .subscribe(() => {
-        this.fireQuery().subscribe(result => {
+    if (!(this.globalRefresh)) {
+      this.fireQuery().subscribe(result => this.processQueryResult(result));
+
+      this.intervalSubject = new BehaviorSubject<number>(this.refreshIntervalInSeconds);
+      this.subscription = this.intervalSubject.pipe(
+        switchMap(val => interval(val * 1000)))
+        .pipe(exhaustMap(() => this.fireQuery()))
+        .subscribe((result) => {
           this.processQueryResult(result);
         });
-      });
+    }
   }
 
   prepareConfigExtraction() {
@@ -112,7 +124,13 @@
   }
 
   ngOnDestroy(): void {
-    this.subscription.unsubscribe();
+    if (this.subscription) {
+      this.subscription.unsubscribe();
+      this.intervalSubject.unsubscribe();
+    }
+    if (this.resizeSub) {
+      this.resizeSub.unsubscribe();
+    }
   }
 
   computeCurrentWidth(width: number): number {
@@ -149,15 +167,6 @@
     }
   }
 
-  onResize(info: WidgetInfo) {
-    if (info.id === this.widgetConfig._id) {
-      setTimeout(() => {
-        this.onSizeChanged(this.computeCurrentWidth(info.width),
-          this.computeCurrentHeight(info.height));
-      }, 100);
-    }
-  }
-
   fireQuery(): Observable<SpQueryResult> {
     return this.dataLakeService
       .getData(this.widgetDataConfig.measureName, this.buildQuery(), true)
@@ -181,8 +190,47 @@
     }
   }
 
-  buildQuery() {
+  public buildQuery(includeMeasure = false): DatalakeQueryParameters {
     const queryBuilder = DatalakeQueryParameterBuilder.create();
-    return queryBuilder.withLimit(this.queryLimit).withOrdering('DESC').build();
+    const columns = this.getFieldsToQuery();
+    if (columns) {
+      if (this.hasOnlyDimensionFields(this.widgetDataConfig.eventSchema.eventProperties, columns)) {
+        const firstMeasurementField = this.getAnyMeasurementField(this.widgetDataConfig.eventSchema.eventProperties);
+        columns.push(firstMeasurementField);
+      }
+      const fields: FieldConfig[] = columns.map(f => {
+        return {runtimeName: f, selected: false, numeric: false};
+      });
+      queryBuilder.withColumnFilter(fields, false);
+    }
+
+    const queryParams = queryBuilder
+      .withLimit(this.queryLimit)
+      .withOrdering('DESC')
+      .build();
+
+    if (includeMeasure) {
+      queryParams.measureName = this.widgetDataConfig.measureName;
+      queryParams.forId = this.widgetConfig._id;
+    }
+
+    return queryParams;
   }
+
+  getAnyMeasurementField(eventProperties: EventPropertyUnion[]): string {
+    return eventProperties
+      .filter(ep => ep instanceof EventPropertyPrimitive)
+      .find(ep => ep.propertyScope === 'MEASUREMENT_PROPERTY').runtimeName;
+  }
+
+  hasOnlyDimensionFields(eventProperties: EventPropertyUnion[],
+                         columns: string[]): boolean {
+    return columns
+      .map(column => eventProperties
+        .find(ep => ep.runtimeName === column))
+      .filter(ep => ep instanceof EventPropertyPrimitive)
+      .every(ep => (ep as EventPropertyPrimitive).propertyScope === 'DIMENSION_PROPERTY');
+  }
+
+  abstract getFieldsToQuery(): string[];
 }
diff --git a/ui/src/app/dashboard/components/widgets/gauge/gauge-widget.component.ts b/ui/src/app/dashboard/components/widgets/gauge/gauge-widget.component.ts
index f1993ed..14d351b 100644
--- a/ui/src/app/dashboard/components/widgets/gauge/gauge-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/gauge/gauge-widget.component.ts
@@ -68,4 +68,8 @@
         return 1;
     }
 
+    getFieldsToQuery(): string[] {
+        return [this.selectedProperty];
+    }
+
 }
diff --git a/ui/src/app/dashboard/components/widgets/html/html-widget.component.ts b/ui/src/app/dashboard/components/widgets/html/html-widget.component.ts
index bce9eff..6e4f759 100644
--- a/ui/src/app/dashboard/components/widgets/html/html-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/html/html-widget.component.ts
@@ -66,4 +66,8 @@
         return 1;
     }
 
+    getFieldsToQuery(): string[] {
+        return [this.selectedHtmlField];
+    }
+
 }
diff --git a/ui/src/app/dashboard/components/widgets/image/image-widget.component.ts b/ui/src/app/dashboard/components/widgets/image/image-widget.component.ts
index f2129ad..9423732 100644
--- a/ui/src/app/dashboard/components/widgets/image/image-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/image/image-widget.component.ts
@@ -74,4 +74,8 @@
         return 1;
     }
 
+    getFieldsToQuery(): string[] {
+        return [this.selectedProperty];
+    }
+
 }
diff --git a/ui/src/app/dashboard/components/widgets/map/map-widget.component.ts b/ui/src/app/dashboard/components/widgets/map/map-widget.component.ts
index 37fc542..ee0f7e8 100644
--- a/ui/src/app/dashboard/components/widgets/map/map-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/map/map-widget.component.ts
@@ -83,6 +83,10 @@
         this.centerMap = extractor.selectedSingleValue(MapConfig.CENTER_MAP_KEY) === 'Center';
     }
 
+    getFieldsToQuery(): string[] {
+        return [this.selectedLatitudeField, this.selectedLongitudeField, ...this.idsToDisplay];
+    }
+
     markerImage(selectedMarker: string): string {
         return selectedMarker === 'Default' ? 'assets/img/marker-icon.png' : 'assets/img/pe_icons/car.png';
     }
diff --git a/ui/src/app/dashboard/components/widgets/number/number-widget.component.ts b/ui/src/app/dashboard/components/widgets/number/number-widget.component.ts
index 1c36326..a05edab 100644
--- a/ui/src/app/dashboard/components/widgets/number/number-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/number/number-widget.component.ts
@@ -21,8 +21,7 @@
 import { StaticPropertyExtractor } from '../../../sdk/extractor/static-property-extractor';
 import { NumberConfig } from './number-config';
 import { ResizeService } from '../../../services/resize.service';
-import { DashboardService } from '../../../services/dashboard.service';
-import { DatalakeRestService, EventPropertyPrimitive } from '@streampipes/platform-services';
+import { DashboardService, DatalakeRestService, EventPropertyPrimitive } from '@streampipes/platform-services';
 
 @Component({
   selector: 'number-widget',
@@ -66,7 +65,7 @@
 
   protected onEvent(events: any[]) {
     let value = events[0][this.selectedProperty];
-    if (!isNaN(value)) {
+    if (typeof value === 'number') {
       value = value.toFixed(2);
     }
     this.item = value;
@@ -79,4 +78,8 @@
     return 1;
   }
 
+  getFieldsToQuery(): string[] {
+    return [this.selectedProperty];
+  }
+
 }
diff --git a/ui/src/app/dashboard/components/widgets/raw/raw-widget.component.ts b/ui/src/app/dashboard/components/widgets/raw/raw-widget.component.ts
index d4f6708..d7e6288 100644
--- a/ui/src/app/dashboard/components/widgets/raw/raw-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/raw/raw-widget.component.ts
@@ -65,4 +65,8 @@
         return extractor.integerParameter(WidgetConfigBuilder.QUERY_LIMIT_KEY);
     }
 
+    getFieldsToQuery(): string[] {
+        return undefined;
+    }
+
 }
diff --git a/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.html b/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.html
index d4cf255..59b7f59 100644
--- a/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.html
+++ b/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.html
@@ -20,9 +20,9 @@
     <div class="title-panel mt-20" *ngIf="hasTitlePanelSettings">
         {{selectedTitle}}
     </div>
-    <div class="value-panel">
-        <div echarts [options]="chartOption" [ngStyle]="{'width': '100%', 'height': currentHeight}"
-             (chartInit)="onChartInit($event)" [merge]= "dynamicData" *ngIf="configReady">
+    <div fxFlex [ngStyle]="{height: currentHeight + 'px'}" *ngIf="configReady">
+        <div echarts [options]="chartOption" [ngStyle]="{'width': '100%', 'height': '100%'}"
+             (chartInit)="onChartInit($event)" [merge]= "dynamicData">
         </div>
     </div>
 </div>
diff --git a/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.scss b/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.scss
index 76e1caf..e374f5d 100644
--- a/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.scss
+++ b/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.scss
@@ -30,15 +30,6 @@
   font-size: 20px;
 }
 
-.value-panel {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  align-content: center;
-  flex: 1;
-}
-
 .status-light {
   border-radius: 50%;
   float: left;
diff --git a/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.ts b/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.ts
index d7cd1da..3bf42bc 100644
--- a/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/stacked-line-chart/stacked-line-chart-widget.component.ts
@@ -24,7 +24,7 @@
 import { EChartsOption } from 'echarts';
 import { DatalakeRestService } from '@streampipes/platform-services';
 import { BaseNgxLineChartsStreamPipesWidget } from '../base/base-ngx-line-charts-widget';
-import { WidgetConfigBuilder } from "../../../registry/widget-config-builder";
+import { WidgetConfigBuilder } from '../../../registry/widget-config-builder';
 
 
 @Component({
@@ -39,6 +39,12 @@
   timestampField: string;
 
   chartOption = {
+    grid: {
+      left: 50,
+      top: 10,
+      right: 50,
+      bottom: 100
+    },
     tooltip: {
       trigger: 'axis',
       formatter (params) {
@@ -71,11 +77,12 @@
       }
     },
     series: [],
-    animationDuration: 500
+    animationDuration: 300
   };
 
   constructor(dataLakeService: DatalakeRestService, resizeService: ResizeService) {
     super(dataLakeService, resizeService);
+    this.configReady = true;
   }
 
   protected extractConfig(extractor: StaticPropertyExtractor) {
@@ -84,38 +91,38 @@
     this.chartOption.yAxis.axisLabel.textStyle.color = this.selectedPrimaryTextColor;
   }
 
-  protected onEvent(event: any) {
+  getFieldsToQuery(): string[] {
+    return this.valueFields;
+  }
+
+  protected onEvent(events: any) {
     this.dynamicData = this.chartOption;
-    const timestamp = event[BaseNgxLineChartsStreamPipesWidget.TIMESTAMP_KEY];
+    this.dynamicData.series = [];
+
     this.valueFields.forEach(field => {
-      if (this.dynamicData.series.some(d => d.name === field)) {
-        const date = new Date(timestamp);
-        this.dynamicData.series.find(d => d.name === field).data.push(
-            {'name': date.toString(), value: [timestamp, event[field]]}
-        );
-        if (this.dynamicData.series.find(d => d.name === field).data.length > 5) {
-          this.dynamicData.series.find(d => d.name === field).data.shift();
-        }
-      } else {
-        this.dynamicData.series.push(this.makeNewSeries(field, timestamp, event[field]));
-      }
+      const series = this.makeNewSeries(field);
+      series.data = events.map(event => {
+        const timestamp = event[BaseNgxLineChartsStreamPipesWidget.TIMESTAMP_KEY];
+        return {
+          'name': timestamp.toString(),
+          value: [timestamp, event[field]]
+        };
+      });
+      this.dynamicData.series.push(series);
     });
 
     if (this.eChartsInstance) {
       this.eChartsInstance.setOption(this.dynamicData as EChartsOption);
     }
+
   }
 
-  makeNewSeries(seriesName, timestamp, value) {
-    const date = new Date(timestamp);
+  makeNewSeries(seriesName: string): any {
     return {
       type: 'line',
       smooth: true,
       name: seriesName,
-      data: [{
-        'name': date.toString(),
-        value: [timestamp, value]
-      }],
+      data: [],
     };
   }
 
diff --git a/ui/src/app/dashboard/components/widgets/status/status-widget.component.ts b/ui/src/app/dashboard/components/widgets/status/status-widget.component.ts
index 6d08ddf..c8658c8 100644
--- a/ui/src/app/dashboard/components/widgets/status/status-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/status/status-widget.component.ts
@@ -72,4 +72,8 @@
     return 1;
   }
 
+  getFieldsToQuery(): string[] {
+    return undefined;
+  }
+
 }
diff --git a/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts b/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
index d291899..65360b0 100644
--- a/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
@@ -34,6 +34,7 @@
 export class TableWidgetComponent extends BaseStreamPipesWidget implements OnInit, OnDestroy {
 
     selectedProperties: string[];
+    fields: string[];
 
     displayedColumns: string[] = [];
     dataSource = new MatTableDataSource();
@@ -61,9 +62,14 @@
 
     extractConfig(extractor: StaticPropertyExtractor) {
         this.selectedProperties = extractor.mappingPropertyValues(TableConfig.SELECTED_PROPERTIES_KEYS);
+        this.fields = extractor.mappingPropertyValues(TableConfig.SELECTED_PROPERTIES_KEYS);
         this.selectedProperties.push(BaseStreamPipesWidget.TIMESTAMP_KEY);
     }
 
+    getFieldsToQuery(): string[] {
+        return this.fields;
+    }
+
     protected onEvent(events: any[]) {
         this.dataSource.data = events.map(ev => this.createTableObject(ev)).reverse();
         this.dataSource.data = [...this.dataSource.data];
diff --git a/ui/src/app/dashboard/components/widgets/trafficlight/traffic-light-widget.component.ts b/ui/src/app/dashboard/components/widgets/trafficlight/traffic-light-widget.component.ts
index 8681357..c008362 100644
--- a/ui/src/app/dashboard/components/widgets/trafficlight/traffic-light-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/trafficlight/traffic-light-widget.component.ts
@@ -80,6 +80,9 @@
         this.selectedLimitGreaterThan = extractor.selectedSingleValue(TrafficLightConfig.CRITICAL_VALUE_LIMIT) === 'Upper Limit';
     }
 
+    getFieldsToQuery(): string[] {
+        return [this.selectedFieldToObserve];
+    }
 
     protected onEvent(events: any[]) {
         const item = events[0][this.selectedFieldToObserve];
diff --git a/ui/src/app/dashboard/components/widgets/wordcloud/wordcloud-widget.component.ts b/ui/src/app/dashboard/components/widgets/wordcloud/wordcloud-widget.component.ts
index 0a08634..aa8a237 100644
--- a/ui/src/app/dashboard/components/widgets/wordcloud/wordcloud-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/wordcloud/wordcloud-widget.component.ts
@@ -106,6 +106,10 @@
     this.windowSize = extractor.integerParameter(WordCloudConfig.WINDOW_SIZE_KEY);
   }
 
+  getFieldsToQuery(): string[] {
+    return [this.countProperty, this.nameProperty];
+  }
+
   protected onEvent(event: any) {
     const value = event[this.countProperty];
     const name = event[this.nameProperty];
diff --git a/ui/src/app/dashboard/dashboard.can-deactivate.guard.ts b/ui/src/app/dashboard/dashboard.can-deactivate.guard.ts
new file mode 100644
index 0000000..b720de5
--- /dev/null
+++ b/ui/src/app/dashboard/dashboard.can-deactivate.guard.ts
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot } from '@angular/router';
+import { Observable } from 'rxjs';
+import { DashboardPanelComponent } from './components/panel/dashboard-panel.component';
+
+@Injectable({providedIn: 'root'})
+export class DashboardPanelCanDeactivateGuard implements CanDeactivate<DashboardPanelComponent> {
+
+  canDeactivate(
+    component: DashboardPanelComponent,
+    route: ActivatedRouteSnapshot,
+    state: RouterStateSnapshot
+  ): Observable<boolean> | boolean {
+
+    return component.confirmLeaveDashboard(route, state);
+  }
+}
diff --git a/ui/src/app/dashboard/dashboard.component.css b/ui/src/app/dashboard/dashboard.component.css
deleted file mode 100644
index 8e7687a..0000000
--- a/ui/src/app/dashboard/dashboard.component.css
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-.mr-20 {
-    margin-right:20px;
-}
-
-.dashboard-panel {
-    height: 100%;
-    flex-direction: column;
-    box-sizing: border-box;
-    display: flex;
-    flex: 1 1 100%;
-    overflow-y: auto;
-}
\ No newline at end of file
diff --git a/ui/src/app/dashboard/dashboard.component.html b/ui/src/app/dashboard/dashboard.component.html
deleted file mode 100644
index 7cb4e9c..0000000
--- a/ui/src/app/dashboard/dashboard.component.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div fxLayout="column" class="page-container">
-    <div fxLayout="row" class="p-0 sp-tab-bg">
-        <div fxFlex="100" class="page-container-nav">
-            <div fxFlex="100" fxLayout="row">
-                <div fxFlex fxLayoutAlign="start center">
-                    <mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="selectDashboard($event)" color="accent">
-                        <mat-tab label="Start"></mat-tab>
-                        <mat-tab *ngFor="let dashboard of dashboards" label="{{dashboard.name}}"></mat-tab>
-                    </mat-tab-group>
-                </div>
-                <div fxFlex fxLayoutAlign="end center" class="mr-20">
-                <button mat-button mat-icon-button color="accent"
-                        *ngIf="selectedIndex > 0 && hasDashboardWritePrivileges" (click)="toggleEditMode()" [disabled]="editMode">
-                    <i class="material-icons">edit</i>
-                </button>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <div class="fixed-height" fxLayout="column" fxFlex="100" *ngIf="dashboardsLoaded">
-    <dashboard-overview (selectDashboardEmitter)="openDashboard($event)"
-                        (reloadDashboardsEmitter)="getDashboards()"
-                        [dashboards]="dashboards"
-                        *ngIf="!dashboardTabSelected">
-
-    </dashboard-overview>
-    <dashboard-panel fxLayout="column" [(editMode)]="editMode" [dashboard]="selectedDashboard"
-                     class="dashboard-panel" *ngIf="dashboardTabSelected">
-
-    </dashboard-panel>
-    </div>
-</div>
diff --git a/ui/src/app/dashboard/dashboard.component.ts b/ui/src/app/dashboard/dashboard.component.ts
deleted file mode 100644
index a8d11f4..0000000
--- a/ui/src/app/dashboard/dashboard.component.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, OnInit } from '@angular/core';
-import { Dashboard } from '@streampipes/platform-services';
-import { DashboardService } from './services/dashboard.service';
-import { RefreshDashboardService } from './services/refresh-dashboard.service';
-import { Tuple2 } from '../core-model/base/Tuple2';
-import { EditModeService } from './services/edit-mode.service';
-import { ActivatedRoute } from '@angular/router';
-import { AuthService } from '../services/auth.service';
-import { UserPrivilege } from '../_enums/user-privilege.enum';
-
-@Component({
-    selector: 'dashboard',
-    templateUrl: './dashboard.component.html',
-    styleUrls: ['./dashboard.component.css']
-})
-export class DashboardComponent implements OnInit {
-
-    selectedDashboard: Dashboard;
-    selectedIndex = 0;
-    dashboardsLoaded = false;
-    dashboardTabSelected = false;
-
-    editMode = false;
-
-    dashboards: Dashboard[];
-    hasDashboardWritePrivileges = false;
-
-    routeParams: any;
-
-    constructor(private dashboardService: DashboardService,
-                private refreshDashboardService: RefreshDashboardService,
-                private editModeService: EditModeService,
-                private route: ActivatedRoute,
-                private authService: AuthService) {}
-
-    ngOnInit() {
-        this.hasDashboardWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_DASHBOARD);
-        this.route.queryParams.subscribe(params => {
-            this.getDashboards(params['dashboardId']);
-        });
-        this.refreshDashboardService.refreshSubject.subscribe(currentDashboardId => {
-            this.getDashboards(currentDashboardId);
-        });
-        this.editModeService.editModeSubject.subscribe(editMode => {
-            this.editMode = editMode;
-        });
-
-    }
-
-    openDashboard(data: Tuple2<Dashboard, boolean>) {
-        const index = this.dashboards.indexOf(data.a);
-        this.editMode = data.b;
-        this.selectDashboard((index + 1));
-    }
-
-    selectDashboard(index: number) {
-        this.selectedIndex = index;
-        if (index === 0) {
-            this.dashboardTabSelected = false;
-        } else {
-            this.dashboardTabSelected = true;
-            this.selectedDashboard = this.dashboards[(index - 1)];
-        }
-    }
-
-    protected getDashboards(currentDashboardId?: string) {
-        this.dashboardsLoaded = false;
-        this.dashboardService.getDashboards().subscribe(data => {
-            this.dashboards = data.sort((a, b) => a.name.localeCompare(b.name));
-            if (currentDashboardId) {
-                const currentDashboard = this.dashboards.find(d => d._id === currentDashboardId);
-                this.selectDashboard(this.dashboards.indexOf(currentDashboard) + 1);
-            } else {
-                this.selectedIndex = 0;
-            }
-            this.dashboardsLoaded = true;
-        });
-    }
-
-    toggleEditMode() {
-        this.editMode = ! (this.editMode);
-    }
-}
diff --git a/ui/src/app/dashboard/dashboard.module.ts b/ui/src/app/dashboard/dashboard.module.ts
index 3072ee1..a736ce9 100644
--- a/ui/src/app/dashboard/dashboard.module.ts
+++ b/ui/src/app/dashboard/dashboard.module.ts
@@ -20,7 +20,6 @@
 import { CommonModule } from '@angular/common';
 import { FlexLayoutModule } from '@angular/flex-layout';
 import { GridsterModule } from 'angular-gridster2';
-import { DashboardComponent } from './dashboard.component';
 import { DashboardPanelComponent } from './components/panel/dashboard-panel.component';
 import { MatTabsModule } from '@angular/material/tabs';
 import { DashboardWidgetComponent } from './components/widget/dashboard-widget.component';
@@ -29,7 +28,6 @@
 import { ColorPickerModule } from 'ngx-color-picker';
 import { AddVisualizationDialogComponent } from './dialogs/add-widget/add-visualization-dialog.component';
 import { MatGridListModule } from '@angular/material/grid-list';
-import { DashboardService } from './services/dashboard.service';
 import { NumberWidgetComponent } from './components/widgets/number/number-widget.component';
 import { DashboardOverviewComponent } from './components/overview/dashboard-overview.component';
 import { EditDashboardDialogComponent } from './dialogs/edit-dashboard/edit-dashboard-dialog.component';
@@ -60,69 +58,89 @@
 import { ReloadPipelineService } from './services/reload-pipeline.service';
 import { PlatformServicesModule } from '@streampipes/platform-services';
 import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
-import { ServicesModule } from "../services/services.module";
+import { ServicesModule } from '../services/services.module';
+import { RouterModule } from '@angular/router';
+import { SharedUiModule } from '@streampipes/shared-ui';
+import { DataExplorerPanelCanDeactivateGuard } from '../data-explorer/data-explorer-panel.can-deactivate.guard';
+import { DashboardPanelCanDeactivateGuard } from './dashboard.can-deactivate.guard';
 
 @NgModule({
-    imports: [
-        NgxEchartsModule.forRoot({
-            /**
-             * This will import all modules from echarts.
-             * If you only need custom modules,
-             * please refer to [Custom Build] section.
-             */
-            echarts: () => import('echarts'),
-        }),
-        CommonModule,
-        CoreUiModule,
-        MatTabsModule,
-        GridsterModule,
-        FlexLayoutModule,
-        CustomMaterialModule,
-        FormsModule,
-        ColorPickerModule,
-        MatGridListModule,
-        NgxChartsModule,
-        CdkTableModule,
-        LeafletModule,
-        PlatformServicesModule,
-        ServicesModule
-    ],
-    declarations: [
-        BarRaceWidgetComponent,
-        DashboardComponent,
-        DashboardGridComponent,
-        DashboardOverviewComponent,
-        DashboardPanelComponent,
-        DashboardWidgetComponent,
-        AddVisualizationDialogComponent,
-        EditDashboardDialogComponent,
-        AreaWidgetComponent,
-        LineWidgetComponent,
-        NumberWidgetComponent,
-        TableWidgetComponent,
-        GaugeWidgetComponent,
-        ImageWidgetComponent,
-        MapWidgetComponent,
-        RawWidgetComponent,
-        StackedLineChartWidgetComponent,
-        HtmlWidgetComponent,
-        StatusWidgetComponent,
-        TrafficLightWidgetComponent,
-        WordcloudWidgetComponent,
-        StandaloneDashboardComponent
-    ],
-    providers: [
-        DashboardService,
-        EditModeService,
-        ReloadPipelineService,
-        ResizeService,
-        RefreshDashboardService,
-        SemanticTypeUtilsService
-    ],
-    exports: [
-        DashboardComponent,
-        DashboardWidgetComponent
-    ]
+  imports: [
+    NgxEchartsModule.forRoot({
+      /**
+       * This will import all modules from echarts.
+       * If you only need custom modules,
+       * please refer to [Custom Build] section.
+       */
+      echarts: () => import('echarts'),
+    }),
+    CommonModule,
+    CoreUiModule,
+    MatTabsModule,
+    GridsterModule,
+    FlexLayoutModule,
+    CustomMaterialModule,
+    FormsModule,
+    ColorPickerModule,
+    MatGridListModule,
+    NgxChartsModule,
+    CdkTableModule,
+    LeafletModule,
+    PlatformServicesModule,
+    ServicesModule,
+    SharedUiModule,
+    RouterModule.forChild([
+      {
+        path: 'dashboard',
+        children: [
+          {
+            path: '',
+            component: DashboardOverviewComponent
+          },
+          {
+            path: ':id',
+            component: DashboardPanelComponent,
+            canDeactivate: [DashboardPanelCanDeactivateGuard]
+          }
+        ]
+      }
+    ]),
+    SharedUiModule,
+  ],
+  declarations: [
+    BarRaceWidgetComponent,
+    DashboardGridComponent,
+    DashboardOverviewComponent,
+    DashboardPanelComponent,
+    DashboardWidgetComponent,
+    AddVisualizationDialogComponent,
+    EditDashboardDialogComponent,
+    AreaWidgetComponent,
+    LineWidgetComponent,
+    NumberWidgetComponent,
+    TableWidgetComponent,
+    GaugeWidgetComponent,
+    ImageWidgetComponent,
+    MapWidgetComponent,
+    RawWidgetComponent,
+    StackedLineChartWidgetComponent,
+    HtmlWidgetComponent,
+    StatusWidgetComponent,
+    TrafficLightWidgetComponent,
+    WordcloudWidgetComponent,
+    StandaloneDashboardComponent
+  ],
+  providers: [
+    EditModeService,
+    ReloadPipelineService,
+    ResizeService,
+    RefreshDashboardService,
+    SemanticTypeUtilsService
+  ],
+  exports: [
+    DashboardWidgetComponent,
+    StandaloneDashboardComponent
+  ]
 })
 export class DashboardModule {
 
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/dashboard/dashboard.routes.ts
similarity index 81%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/dashboard/dashboard.routes.ts
index 58ba04b..57da4a1 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/dashboard/dashboard.routes.ts
@@ -16,3 +16,10 @@
  *
  */
 
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+
+export class SpDashboardRoutes {
+
+  static BASE: SpBreadcrumbItem = {label: 'Dashboards', link: ['dashboard']};
+
+}
diff --git a/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.html b/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.html
index 45c650a..5142e8c 100644
--- a/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.html
+++ b/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.html
@@ -26,7 +26,7 @@
                         <mat-list-item *ngFor="let pipeline of visualizablePipelines"
                                        (click)="selectPipeline(pipeline)"
                                        class="list-item"
-                                        [attr.data-cy]="'dashboard-visualize-pipeline-' + pipeline.pipelineName">
+                                        [attr.data-cy]="'dashboard-visualize-pipeline-' + pipeline.pipelineName.replaceAll(' ', '_')">
                             <div mat-list-avatar
                                  class="pipeline-avatar sp-accent-bg">{{iconText(pipeline.measureName)}}
                             </div>
diff --git a/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.ts b/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.ts
index 2b65f47..538408d 100644
--- a/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.ts
+++ b/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.ts
@@ -21,9 +21,9 @@
 import { WidgetConfigBuilder } from '../../registry/widget-config-builder';
 import { WidgetRegistry } from '../../registry/widget-registry';
 import { MappingPropertyGenerator } from '../../sdk/matching/mapping-property-generator';
-import { DashboardService } from '../../services/dashboard.service';
 import {
   Dashboard,
+  DashboardService,
   DashboardWidgetModel,
   DashboardWidgetSettings,
   DataLakeMeasure, DatalakeRestService,
diff --git a/ui/src/app/dashboard/dialogs/edit-dashboard/edit-dashboard-dialog.component.html b/ui/src/app/dashboard/dialogs/edit-dashboard/edit-dashboard-dialog.component.html
index a653ab0..d45e60a 100644
--- a/ui/src/app/dashboard/dialogs/edit-dashboard/edit-dashboard-dialog.component.html
+++ b/ui/src/app/dashboard/dialogs/edit-dashboard/edit-dashboard-dialog.component.html
@@ -33,7 +33,18 @@
                 </mat-form-field>
                 <mat-checkbox [(ngModel)]="dashboard.displayHeader">Show name and description in dashboard
                 </mat-checkbox>
+                <div fxLayout="column" class="mt-10">
+                    <mat-checkbox [(ngModel)]="dashboard.dashboardGeneralSettings.globalRefresh">
+                        Use same update frequency for all widgets (will override widget-specific intervals)
+                    </mat-checkbox>
 
+                    <mat-form-field class="full-width mt-10"
+                                    color="accent"
+                                    *ngIf="dashboard.dashboardGeneralSettings.globalRefresh">
+                        <mat-label>Refresh interval (seconds)</mat-label>
+                        <input matInput [(ngModel)]="dashboard.dashboardGeneralSettings.refreshIntervalInSeconds">
+                    </mat-form-field>
+                </div>
             </div>
         </div>
     </div>
diff --git a/ui/src/app/dashboard/dialogs/edit-dashboard/edit-dashboard-dialog.component.ts b/ui/src/app/dashboard/dialogs/edit-dashboard/edit-dashboard-dialog.component.ts
index 26be5b4..a9461f0 100644
--- a/ui/src/app/dashboard/dialogs/edit-dashboard/edit-dashboard-dialog.component.ts
+++ b/ui/src/app/dashboard/dialogs/edit-dashboard/edit-dashboard-dialog.component.ts
@@ -17,8 +17,7 @@
  */
 
 import { Component, Input } from '@angular/core';
-import { DashboardService } from '../../services/dashboard.service';
-import { Dashboard } from '@streampipes/platform-services';
+import { Dashboard, DashboardService } from '@streampipes/platform-services';
 import { DialogRef } from '@streampipes/shared-ui';
 
 @Component({
diff --git a/ui/src/app/dashboard/services/resize.service.ts b/ui/src/app/dashboard/services/resize.service.ts
index 129f7c2..32101c3 100644
--- a/ui/src/app/dashboard/services/resize.service.ts
+++ b/ui/src/app/dashboard/services/resize.service.ts
@@ -18,14 +18,14 @@
 
 import { Subject } from 'rxjs';
 import { Injectable } from '@angular/core';
-import { WidgetInfo } from '../models/gridster-info.model';
+import { GridsterInfo } from '../models/gridster-info.model';
 
 @Injectable()
 export class ResizeService {
 
-    public resizeSubject: Subject<WidgetInfo> = new Subject<WidgetInfo>();
+    public resizeSubject: Subject<GridsterInfo> = new Subject<GridsterInfo>();
 
-    public notify(info: WidgetInfo): void {
+    public notify(info: GridsterInfo): void {
         this.resizeSubject.next(info);
     }
 }
diff --git a/ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.html b/ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.html
deleted file mode 100644
index 8334031..0000000
--- a/ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<mat-toolbar>
-    <div class="md-toolbar-tools">
-        <h2>Download Data</h2>
-        <span fxFlex></span>
-        <button mat-icon-button (click)="exitDialog()">
-            <i class="material-icons">close</i>
-        </button>
-    </div>
-</mat-toolbar>
-
-<div mat-dialog-content class="md-dialog-content">
-
-
-    <mat-horizontal-stepper  #stepper>
-        <mat-step>
-            <ng-template matStepLabel>Select Data</ng-template>
-            <div>
-                <mat-radio-group class="example-radio-group" [(ngModel)]="selectedData">
-<!--                    <mat-radio-button value="visible" class="example-radio-button">-->
-<!--                        Visible data in charts-->
-<!--                    </mat-radio-button>-->
-                    <mat-radio-button value="all" class="example-radio-button">
-                        All data in database
-                    </mat-radio-button>
-                    <mat-radio-button value="customInterval" class="example-radio-button">
-                        All data in custom time interval
-                    </mat-radio-button>
-                </mat-radio-group>
-                <div fxLayout="row" fxLayoutAlign="start center" class="ml-35">
-                    <mat-form-field class="form-field-date">
-                        <input matInput [owlDateTime]="dt1" [owlDateTimeTrigger]="dt1"
-                               [(ngModel)]="dateRange" [selectMode]="'range'" [disabled]="selectedData !== 'customInterval'">
-                        <mat-icon matSuffix [owlDateTimeTrigger]="dt1" *ngIf="selectedData === 'customInterval'">event</mat-icon>
-                        <mat-icon matSuffix class="event-color" *ngIf="selectedData !== 'customInterval'">event</mat-icon>
-                        <owl-date-time #dt1></owl-date-time>
-                    </mat-form-field>
-                </div>
-            </div>
-        </mat-step>
-
-
-
-        <mat-step>
-            <ng-template matStepLabel>Select Format</ng-template>
-            <div>
-                <mat-radio-group class="example-radio-group" [(ngModel)]="downloadFormat">
-                    <mat-radio-button value="json" class="example-radio-button">
-                        JSON
-                    </mat-radio-button>
-                    <mat-radio-button value="csv" class="example-radio-button">
-                        CSV
-                    </mat-radio-button>
-                </mat-radio-group>
-            </div>
-        </mat-step>
-
-
-
-
-
-        <mat-step>
-            <ng-template matStepLabel>Download</ng-template>
-            <div div fxLayout="column" fxLayoutAlign="space-around center" *ngIf="!downloadFinish">
-                <mat-spinner></mat-spinner>
-                <label *ngIf="downloadedMBs !== undefined">{{downloadedMBs      | number : '1.0-2' }} Mb</label>
-                <button mat-button warn  color="warn" (click)="cancelDownload()">Cancel</button>
-            </div>
-            <div div fxLayout="column" fxLayoutAlign="space-around center" *ngIf="downloadFinish">
-                <mat-icon class="icon-check">check</mat-icon>
-            </div>
-        </mat-step>
-    </mat-horizontal-stepper>
-
-</div>
-
-<mat-divider></mat-divider>
-<div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center">
-    <button mat-button *ngIf="stepper.selectedIndex == 1" color="primary" (click)="previousStep()">Previous</button>
-    <button mat-button mat-raised-button *ngIf="stepper.selectedIndex < 1" color="primary" (click)="nextStep()">Next</button>
-    <button mat-button mat-raised-button *ngIf="stepper.selectedIndex == 1" color="accent" (click)="downloadData()">Download</button>
-    <button mat-button mat-raised-button *ngIf="downloadFinish" color="primary" (click)="exitDialog()">Close</button>
-</div>
diff --git a/ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.ts b/ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.ts
deleted file mode 100644
index 794fbf9..0000000
--- a/ui/src/app/data-explorer/components/datadownloadDialog/dataDownload.dialog.ts
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { HttpEventType } from '@angular/common/http';
-import { Component, Inject, ViewChild } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
-import { MatStepper } from '@angular/material/stepper';
-import { DatalakeRestService } from '@streampipes/platform-services';
-
-
-@Component({
-    selector: 'sp-data-download-dialog',
-    templateUrl: 'dataDownload.dialog.html',
-    styleUrls: ['./dataDownload.dialog.css']
-})
-// tslint:disable-next-line:component-class-suffix
-export class DataDownloadDialog {
-
-
-    downloadFormat = 'csv';
-    selectedData = 'visible';
-    downloadFinish = false;
-    downloadedMBs: number = undefined;
-
-    @ViewChild('stepper', { static: true }) stepper: MatStepper;
-
-    downloadHttpRequestSubscribtion;
-
-    dateRange: Date [] = []; // [0] start, [1] end
-
-
-    constructor(public dialogRef: MatDialogRef<DataDownloadDialog>,
-                @Inject(MAT_DIALOG_DATA) public data,
-                public datalakeRestService: DatalakeRestService) {
-        this.dateRange[0] = new Date();
-        this.dateRange[1] = new Date(this.dateRange[0].getTime() + 60000 * 60 * 24);
-    }
-
-    downloadData() {
-        this.nextStep();
-        switch (this.selectedData) {
-            case 'all':
-                this.performRequest(this.data.downloadRawData(this.data.index, this.downloadFormat), '', '');
-                break;
-            case 'customInterval':
-                this.performRequest(this.datalakeRestService.downloadQueriedData(this.data.index, this.downloadFormat,
-                    this.dateRange[0].getTime(), this.dateRange[1].getTime()), this.getDateString(this.dateRange[0]),
-                  this.getDateString(this.dateRange[1]));
-
-        }
-    }
-
-    performRequest(request, startDate, endDate) {
-        this.downloadHttpRequestSubscribtion = request.subscribe(event => {
-            // progress
-            if (event.type === HttpEventType.DownloadProgress) {
-                this.downloadedMBs = event.loaded / 1024 / 1014;
-            }
-
-            // finished
-            if (event.type === HttpEventType.Response) {
-                this.createFile(event.body, this.downloadFormat, this.data.index, startDate, endDate);
-                this.downloadFinish = true;
-            }
-        });
-    }
-
-    convertData(data, format, xAxesKey, yAxesKeys) {
-        const indexXKey = data.headers.findIndex(headerName => headerName === xAxesKey);
-        const indicesYKeys = [];
-        yAxesKeys.forEach(key => {
-            indicesYKeys.push(data.headers.findIndex(headerName => headerName === key));
-        });
-
-        if (format === 'json') {
-            const resultJson = [];
-
-
-            data.rows.forEach(row => {
-                const tmp = {'time': new Date(row[indexXKey]).getTime()};
-                indicesYKeys.forEach(index => {
-                    if (row[index] !== undefined) {
-                        tmp[data.headers[index]] = row[index];
-                    }
-                });
-                resultJson.push(tmp);
-            });
-
-            return JSON.stringify(resultJson);
-        } else {
-            // CSV
-            let resultCsv = '';
-
-            // header
-            resultCsv += xAxesKey;
-            yAxesKeys.forEach(key => {
-                resultCsv += ';';
-                resultCsv += key;
-            });
-
-
-            // content
-            data.rows.forEach(row => {
-                resultCsv += '\n';
-                resultCsv += new Date(row[indexXKey]).getTime();
-                indicesYKeys.forEach(index => {
-                    resultCsv += ';';
-                    if (row[index] !== undefined) {
-                        resultCsv += row[index];
-                    }
-                });
-            });
-
-            return resultCsv;
-        }
-    }
-
-    createFile(data, format, fileName, startDate, endDate) {
-        const a = document.createElement('a');
-        document.body.appendChild(a);
-        a.style.display = 'display: none';
-
-        let name = 'sp_' + startDate + '_' + fileName + '.' + this.downloadFormat;
-        name = name.replace('__', '_');
-
-        const url = window.URL.createObjectURL(new Blob([String(data)], { type: 'data:text/' + format + ';charset=utf-8' }));
-        a.href = url;
-        a.download = name;
-        a.click();
-        window.URL.revokeObjectURL(url);
-    }
-
-    cancelDownload() {
-        try {
-            this.downloadHttpRequestSubscribtion.unsubscribe();
-        } finally {
-            this.exitDialog();
-        }
-    }
-
-
-    exitDialog(): void {
-        this.dialogRef.close();
-    }
-
-    nextStep() {
-        this.stepper.next();
-    }
-
-    previousStep() {
-        this.stepper.previous();
-    }
-
-    getDateString(date: Date) {
-        return date.toLocaleDateString() + 'T' + date.toLocaleTimeString().replace(':', '.')
-                                                                          .replace(':', '.');
-    }
-
-}
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
index 8866e18..af0e26f 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
+++ b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
@@ -39,7 +39,8 @@
             <div fxFlex fxLayout="column" class="designer-panel-config">
 
                 <div *ngIf="selectedIndex == 0">
-                    <sp-data-explorer-widget-data-settings [(dataLakeMeasure)]="dataLakeMeasure"
+                    <sp-data-explorer-widget-data-settings #dataSettingsPanel
+                                                           [(dataLakeMeasure)]="dataLakeMeasure"
                                                            [dataConfig]="currentlyConfiguredWidget.dataConfig"
                                                            [newWidgetMode]="newWidgetMode"
                                                            [widgetId]="currentlyConfiguredWidget._id"
@@ -64,6 +65,7 @@
                  *ngIf="newWidgetMode">
                 <button mat-button mat-raised-button color="accent"
                         data-cy="data-explorer-select-data-set-next-btn"
+                        [disabled]="selectedIndex === 0 && (!(currentlyConfiguredWidget.dataConfig.sourceConfigs) || currentlyConfiguredWidget.dataConfig.sourceConfigs.length === 0 || currentlyConfiguredWidget.dataConfig.sourceConfigs[0].measureName === '')"
                         *ngIf="newWidgetMode && selectedIndex == 0"
                         (click)="selectedIndex = 1">
                     Next
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts
index 94af4fa..ec7b7e0 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts
+++ b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts
@@ -16,9 +16,10 @@
  *
  */
 
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
 import { DataExplorerWidgetModel, DataLakeMeasure } from '@streampipes/platform-services';
 import { Tuple2 } from '../../../core-model/base/Tuple2';
+import { DataExplorerWidgetDataSettingsComponent } from './data-settings/data-explorer-widget-data-settings.component';
 
 @Component({
   selector: 'sp-data-explorer-designer-panel',
@@ -38,6 +39,8 @@
 
   selectedIndex = 0;
 
+  dataSettingsPanel: DataExplorerWidgetDataSettingsComponent;
+
   ngOnInit(): void {
   }
 
@@ -51,15 +54,23 @@
     // Set default name to the measure name
     if (this.currentlyConfiguredWidget.dataConfig.sourceConfigs.length > 0) {
       this.currentlyConfiguredWidget.baseAppearanceConfig.widgetTitle =
-        this.currentlyConfiguredWidget.dataConfig.sourceConfigs[0].measureName;
+        this.currentlyConfiguredWidget.dataConfig.sourceConfigs[0].measureName
+        + ' - '
+        + this.currentlyConfiguredWidget.widgetType;
     }
 
     this.addWidgetEmitter.emit({ a: this.dataLakeMeasure, b: this.currentlyConfiguredWidget });
   }
 
-  modifyWidgetMode(widget: DataExplorerWidgetModel, newWidgetMode: boolean) {
+  modifyWidgetMode(widget: DataExplorerWidgetModel,
+                   newWidgetMode: boolean) {
     this.currentlyConfiguredWidget = widget;
     this.newWidgetMode = newWidgetMode;
+    if (this.dataSettingsPanel) {
+      setTimeout(() => {
+        this.dataSettingsPanel.checkSourceTypes();
+      });
+    }
   }
 
   closeDesignerPanel() {
@@ -70,4 +81,9 @@
     this.selectedIndex = 0;
     this.newWidgetMode = true;
   }
+
+  @ViewChild('dataSettingsPanel')
+  public set content(dataSettingsPanel: DataExplorerWidgetDataSettingsComponent) {
+    this.dataSettingsPanel = dataSettingsPanel;
+  }
 }
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html b/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html
index dee6ba4..c276798 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html
+++ b/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html
@@ -48,16 +48,16 @@
                         <mat-radio-group
                                 class="selection-radio-group"
                                 [(ngModel)]="sourceConfig.sourceType">
-                            <mat-radio-button class="selection-radio-button" [value]="'pipeline'">Pipeline
+                            <mat-radio-button class="selection-radio-button" [value]="'pipeline'" [disabled]="availablePipelines.length === 0">Pipeline
                             </mat-radio-button>
                             <mat-radio-button class="selection-radio-button" [value]="'measurement'">Measurement
                             </mat-radio-button>
                         </mat-radio-group>
                     </div>
                     <mat-form-field color="accent" fxFlex="100" *ngIf="sourceConfig.sourceType == 'pipeline'">
-                        <mat-label>Data Explorer Sinks</mat-label>
+                        <mat-label>Select data explorer sink</mat-label>
                         <mat-select [(value)]="sourceConfig.measureName"
-                                    (selectionChange)="updateMeasure(sourceConfig, $event)"
+                                    (selectionChange)="updateMeasure(sourceConfig, $event.value)"
                                     data-cy="data-explorer-select-data-set">
                             <mat-option *ngFor="let pipeline of availablePipelines"
                                         [value]="pipeline.measureName">
@@ -66,9 +66,9 @@
                         </mat-select>
                     </mat-form-field>
                     <mat-form-field color="accent" fxFlex="100" *ngIf="sourceConfig.sourceType == 'measurement'">
-                        <mat-label>Data Lake Measurements</mat-label>
+                        <mat-label>Select measurement</mat-label>
                         <mat-select [(value)]="sourceConfig.measureName"
-                                    (selectionChange)="updateMeasure(sourceConfig, $event)">
+                                    (selectionChange)="updateMeasure(sourceConfig, $event.value)">
                             <mat-option [value]="measurement.measureName"
                                         *ngFor="let measurement of availableMeasurements">
                                 <span class="pipeline-name">{{ measurement.measureName }}</span>
@@ -124,7 +124,8 @@
                 </div>
                 <div fxLayout="column" fxFlex="100" class="data-explorer-options-panel"
                      *ngIf="sourceConfig.queryType && sourceConfig.measure">
-                    <sp-field-selection-panel #fieldSelectionPanel [sourceConfig]="sourceConfig"
+                    <sp-field-selection-panel #fieldSelectionPanel 
+                                              [sourceConfig]="sourceConfig"
                                               [widgetId]="widgetId"></sp-field-selection-panel>
                 </div>
                 <div fxLayout="column" fxFlex="100" class="data-explorer-options-panel"
@@ -134,7 +135,8 @@
                 </div>
                 <div fxLayout="column" fxFlex="100" class="data-explorer-options-panel"
                      *ngIf="sourceConfig.queryType && sourceConfig.measure">
-                    <sp-group-selection-panel [sourceConfig]="sourceConfig"
+                    <sp-group-selection-panel #groupSelectionPanel
+                                              [sourceConfig]="sourceConfig"
                                               [widgetId]="widgetId"></sp-group-selection-panel>
                 </div>
             </div>
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts b/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
index 6bb4c6b..7768df9 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
+++ b/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
@@ -30,6 +30,7 @@
 import { zip } from 'rxjs';
 import { WidgetConfigurationService } from '../../../services/widget-configuration.service';
 import { FieldSelectionPanelComponent } from './field-selection-panel/field-selection-panel.component';
+import { GroupSelectionPanelComponent } from './group-selection-panel/group-selection-panel.component';
 
 @Component({
   selector: 'sp-data-explorer-widget-data-settings',
@@ -51,8 +52,12 @@
   @ViewChild('fieldSelectionPanel')
   fieldSelectionPanel: FieldSelectionPanelComponent;
 
-  availablePipelines: DataLakeMeasure[];
-  availableMeasurements: DataLakeMeasure[];
+  @ViewChild('groupSelectionPanel')
+  groupSelectionPanel: GroupSelectionPanelComponent;
+
+
+  availablePipelines: DataLakeMeasure[] = [];
+  availableMeasurements: DataLakeMeasure[] = [];
 
   step = 0;
 
@@ -79,22 +84,55 @@
         p.eventSchema = measurement.eventSchema;
       });
 
-      if (!this.dataConfig.sourceConfigs) {
-        this.addDataSource();
+      if (!(this.dataConfig.sourceConfigs)) {
+        const defaultConfigs = this.findDefaultConfig();
+        this.addDataSource(defaultConfigs.measureName, defaultConfigs.sourceType);
+        if (defaultConfigs.measureName !== undefined) {
+          this.updateMeasure(this.dataConfig.sourceConfigs[0], defaultConfigs.measureName);
+        }
+      } else {
+        this.checkSourceTypes();
       }
     });
   }
 
-  updateMeasure(sourceConfig: SourceConfig, event: MatSelectChange) {
-    sourceConfig.measure = this.findMeasure(event.value);
+  checkSourceTypes() {
+    this.dataConfig.sourceConfigs.forEach(sourceConfig => {
+      if (sourceConfig.sourceType === 'pipeline' && !this.existsPipelineWithMeasure(sourceConfig.measureName)) {
+        sourceConfig.sourceType = 'measurement';
+      }
+    });
+  }
+
+  existsPipelineWithMeasure(measureName: string) {
+    return this.availablePipelines.find(pipeline => pipeline.measureName === measureName) !== undefined;
+  }
+
+  findDefaultConfig(): { measureName: string, sourceType: 'pipeline' | 'measurement' } {
+    if (this.availablePipelines.length > 0) {
+      return { measureName: this.availablePipelines[0].measureName, sourceType: 'pipeline'};
+    } else if (this.availableMeasurements.length > 0) {
+      return { measureName:  this.availableMeasurements[0].measureName, sourceType: 'measurement'};
+    } else {
+      return { measureName: undefined, sourceType: undefined };
+    }
+  }
+
+  updateMeasure(sourceConfig: SourceConfig, measureName: string) {
+    sourceConfig.measure = this.findMeasure(measureName);
     sourceConfig.queryConfig.fields = [];
     if (this.fieldSelectionPanel) {
       this.fieldSelectionPanel.applyDefaultFields();
     }
 
+    sourceConfig.queryConfig.groupBy = [];
+    if (this.groupSelectionPanel) {
+      this.groupSelectionPanel.applyDefaultFields();
+    }
+
   }
 
-  findMeasure(measureName) {
+  findMeasure(measureName: string) {
     return this.availablePipelines.find(pipeline => pipeline.measureName === measureName) ||
       this.availableMeasurements.find(m => m.measureName === measureName);
   }
@@ -108,16 +146,18 @@
     this.triggerDataRefresh();
   }
 
-  addDataSource() {
+  addDataSource(measureName = '',
+                sourceType: 'pipeline' | 'measurement' = 'pipeline') {
     if (!this.dataConfig.sourceConfigs) {
       this.dataConfig.sourceConfigs = [];
     }
-    this.dataConfig.sourceConfigs.push(this.makeSourceConfig());
+    this.dataConfig.sourceConfigs.push(this.makeSourceConfig(measureName, sourceType));
   }
 
-  makeSourceConfig(): SourceConfig {
+  makeSourceConfig(measureName = '',
+                   sourceType: 'pipeline' | 'measurement' = 'pipeline'): SourceConfig {
     return {
-      measureName: '',
+      measureName,
       queryConfig: {
         selectedFilters: [],
         limit: 100,
@@ -126,7 +166,7 @@
         aggregationValue: 1
       },
       queryType: 'raw',
-      sourceType: 'pipeline'
+      sourceType
     };
   }
 
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts b/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts
index 62bb904..75ecc2f 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts
+++ b/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts
@@ -28,6 +28,8 @@
 })
 export class FieldSelectionPanelComponent implements OnInit {
 
+  MAX_INITIAL_FIELDS = 3;
+
   @Input() sourceConfig: SourceConfig;
   @Input() widgetId: string;
 
@@ -49,6 +51,7 @@
   applyDefaultFields() {
     if (this.sourceConfig.queryConfig.fields.length === 0) {
       this.addAllFields();
+      this.selectInitialFields();
     } else {
       const oldFields = this.sourceConfig.queryConfig.fields;
       this.sourceConfig.queryConfig.fields = [];
@@ -60,8 +63,17 @@
     this.sourceConfig.measure.eventSchema.eventProperties.forEach(property => {
       // this ensures that dimension properties are not aggregated, this is not possible with the influxdb, See [STREAMPIPES-524]
       if (this.sourceConfig.queryType === 'raw' || property.propertyScope !== 'DIMENSION_PROPERTY') {
-        const isSelected = checkFields.some(v => v.runtimeName === property.runtimeName);
-        this.addField(property, isSelected);
+        const fieldConfig = checkFields.find(field => field.runtimeName === property.runtimeName);
+        const isSelected = fieldConfig && fieldConfig.selected;
+        this.addField(property, isSelected, fieldConfig);
+      }
+    });
+  }
+
+  selectInitialFields() {
+    this.sourceConfig.queryConfig.fields.forEach((field, index) => {
+      if (index < this.MAX_INITIAL_FIELDS) {
+        field.selected = true;
       }
     });
   }
@@ -79,12 +91,12 @@
     this.widgetConfigService.notify({widgetId: this.widgetId, refreshData: true, refreshView: true});
   }
 
-  addField(property: EventPropertyUnion, isSelected = false) {
+  addField(property: EventPropertyUnion, isSelected = false, fieldConfig: FieldConfig) {
     const selection: FieldConfig = {
       runtimeName: property.runtimeName,
       selected: isSelected,
       numeric: this.fieldProvider.isNumber(property)};
-    selection.aggregations = [this.findDefaultAggregation(property)];
+    selection.aggregations = fieldConfig && fieldConfig.aggregations ? fieldConfig.aggregations : [this.findDefaultAggregation(property)];
     this.sourceConfig.queryConfig.fields.push(selection);
   }
 
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts b/ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts
index 91ef564..e8f0641 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts
+++ b/ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts
@@ -36,7 +36,9 @@
   }
 
   ngOnInit() {
-    if (this.sourceConfig.queryConfig.groupBy === undefined) {
+    const groupByFields = this.sourceConfig.queryConfig.groupBy;
+
+    if (groupByFields === undefined || groupByFields.length === 0) {
       this.applyDefaultFields();
     }
   }
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts b/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts
deleted file mode 100644
index 45ee85d..0000000
--- a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import {
-  Component,
-  EventEmitter,
-  Input,
-  OnChanges,
-  OnInit,
-  Output,
-  QueryList,
-  SimpleChanges,
-  ViewChildren
-} from '@angular/core';
-import { GridsterItemComponent, GridType } from 'angular-gridster2';
-import { GridsterInfo } from '../../../dashboard/models/gridster-info.model';
-import { IDataViewDashboardConfig } from '../../models/dataview-dashboard.model';
-import { ResizeService } from '../../services/resize.service';
-import {
-  DataViewDataExplorerService,
-  Dashboard,
-  DataExplorerWidgetModel,
-  DataLakeMeasure,
-  TimeSettings
-} from '@streampipes/platform-services';
-
-@Component({
-  selector: 'sp-data-explorer-dashboard-grid',
-  templateUrl: './data-explorer-dashboard-grid.component.html',
-  styleUrls: ['./data-explorer-dashboard-grid.component.scss']
-})
-export class DataExplorerDashboardGridComponent implements OnInit, OnChanges {
-
-  @Input()
-  editMode: boolean;
-
-  _dashboard: Dashboard;
-
-  configuredWidgets: Map<string, DataExplorerWidgetModel> = new Map<string, DataExplorerWidgetModel>();
-  dataLakeMeasures: Map<string, DataLakeMeasure> = new Map<string, DataLakeMeasure>();
-
-  /**
-   * This is the date range (start, end) to view the data and is set in data-explorer.ts
-   */
-  @Input()
-  timeSettings: TimeSettings;
-
-  @Output() deleteCallback: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
-  @Output() updateCallback: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
-  @Output() configureWidgetCallback: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
-  @Output() startEditModeEmitter: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
-
-  options: IDataViewDashboardConfig;
-  loaded = false;
-
-  @Input()
-  currentlyConfiguredWidgetId: string;
-
-  @ViewChildren(GridsterItemComponent) gridsterItemComponents: QueryList<GridsterItemComponent>;
-
-  constructor(private resizeService: ResizeService,
-              private dataViewDataExplorerService: DataViewDataExplorerService) {
-
-  }
-
-  ngOnInit(): void {
-    this.options = {
-      disablePushOnDrag: true,
-      draggable: {enabled: this.editMode},
-      gridType: GridType.VerticalFixed,
-      minCols: 8,
-      maxCols: 8,
-      minRows: 4,
-      fixedRowHeight: 100,
-      fixedColWidth: 100,
-      margin: 5,
-      displayGrid: this.editMode ? 'always' : 'none',
-      resizable: {enabled: this.editMode},
-      itemResizeCallback: ((item, itemComponent) => {
-        this.resizeService.notify({
-          gridsterItem: item,
-          gridsterItemComponent: itemComponent
-        } as GridsterInfo);
-      }),
-      itemInitCallback: ((item, itemComponent) => {
-        this.resizeService.notify({
-          gridsterItem: item,
-          gridsterItemComponent: itemComponent
-        } as GridsterInfo);
-        window.dispatchEvent(new Event('resize'));
-      })
-    };
-  }
-
-  @Input() set dashboard(dashboard: Dashboard) {
-    this._dashboard = dashboard;
-    this.loadWidgetConfigs();
-  }
-
-  get dashboard() {
-    return this._dashboard;
-  }
-
-  loadWidgetConfigs() {
-    this.dashboard.widgets.forEach(widget => {
-      this.loadWidgetConfig(widget.id);
-    });
-
-  }
-
-  loadWidgetConfig(widgetId: string, setCurrentlyConfigured?: boolean) {
-    this.dataViewDataExplorerService.getWidget(widgetId).subscribe(response => {
-      this.configuredWidgets.set(widgetId, response);
-      this.dataLakeMeasures.set(widgetId, response.dataConfig.sourceConfigs[0].measure);
-      if (setCurrentlyConfigured) {
-        this.propagateWidgetSelection(this.configuredWidgets.get(widgetId));
-      }
-    });
-  }
-
-  ngOnChanges(changes: SimpleChanges): void {
-    if (changes['editMode'] && this.options) {
-      this.options.draggable.enabled = this.editMode;
-      this.options.resizable.enabled = this.editMode;
-      this.options.displayGrid = this.editMode ? 'always' : 'none';
-      this.options.api.optionsChanged();
-    }
-  }
-
-  propagateItemRemoval(widget: DataExplorerWidgetModel) {
-    this.deleteCallback.emit(widget);
-  }
-
-  propagateItemUpdate(dashboardWidget: DataExplorerWidgetModel) {
-    this.updateCallback.emit(dashboardWidget);
-  }
-
-  propagateWidgetSelection(configuredWidget: DataExplorerWidgetModel) {
-    this.configureWidgetCallback.emit(configuredWidget);
-    if (configuredWidget) {
-      this.currentlyConfiguredWidgetId = configuredWidget._id;
-    } else {
-      this.currentlyConfiguredWidgetId = undefined;
-    }
-    this.options.api.optionsChanged();
-  }
-
-  toggleGrid() {
-    this.options.displayGrid = this.options.displayGrid === 'none' ? 'always' : 'none';
-    this.options.api.optionsChanged();
-  }
-
-  updateAllWidgets() {
-    this.configuredWidgets.forEach((value, key) => {
-      this.dataViewDataExplorerService.updateWidget(value).subscribe(response => {
-        value._rev = response._rev;
-        this.currentlyConfiguredWidgetId = undefined;
-      });
-    });
-  }
-
-  startEditMode(value: DataExplorerWidgetModel) {
-    this.startEditModeEmitter.emit(value);
-    this.currentlyConfiguredWidgetId = value._id;
-  }
-
-}
diff --git a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
index 67d255d..b7e869a 100644
--- a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
+++ b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
@@ -17,79 +17,91 @@
   -->
 
 
-<div fxFlex="100" fxLayout="column">
-    <div fxFlex="100" fxLayout="column">
-        <div fxLayout="row" class="fixed-height options-bar page-container-nav sp-tab-bg">
-            <div fxLayoutAlign="start center" fxLayout="row" class="pl-10">
-                <button mat-button mat-raised-button color="accent"
-                        data-cy="open-new-data-view-dialog"
-                        (click)="openNewDataViewDialog()" class="mr-10" *ngIf="hasDataExplorerWritePrivileges">
-                    <i class="material-icons">add</i>
-                    <span>New Data View</span>
-                </button>
-            </div>
-        </div>
+<sp-basic-view [showBackLink]="false" [padding]="true">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <button mat-button mat-raised-button color="accent"
+                data-cy="open-new-data-view-dialog"
+                (click)="openNewDataViewDialog()" class="mr-10" *ngIf="hasDataExplorerWritePrivileges">
+            <i class="material-icons">add</i>
+            <span>New Data View</span>
+        </button>
+
     </div>
-    <div *ngIf="!editLabels" fxFlex="100" fxLayout="row wrap" fxLayoutAlign="start stretch" class="m-20">
-        <div fxFlex="100" class="assemblyOptions sp-blue-bg p-5">
-            <div fxLayout="row" fxLayoutAlign="start center" fxFlex="100">
-                <h4>My Data Views</h4>
-                <span fxFlex></span>
-            </div>
-        </div>
-        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="sp-blue-border">
-            <div fxFlex="100" fxLayout="column" class="w-100 p-2">
-                <table mat-table [dataSource]="dataSource" multiTemplateDataRows>
+    <div fxFlex="100" fxLayout="column">
+        <sp-basic-header-title-component title="My Data Views"></sp-basic-header-title-component>
+        <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+            <sp-basic-inner-panel [showTitle]="false" innerPadding="0" outerMargin="0" fxFlex="90" [hideToolbar]="true">
+                <div fxFlex="100" fxLayout="column" class="w-100" *ngIf="dashboards.length > 0">
+                    <table mat-table [dataSource]="dataSource" multiTemplateDataRows>
 
-                    <ng-container matColumnDef="name">
-                        <th fxFlex="60" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Data View</th>
-                        <td fxFlex="60" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
-                            {{element.name}}<br/>
-                            {{element.description}}
-                        </td>
-                    </ng-container>
+                        <ng-container matColumnDef="name">
+                            <th fxFlex="60" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Data View
+                            </th>
+                            <td fxFlex="60" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+                                {{element.name}}<br/>
+                                {{element.description}}
+                            </td>
+                        </ng-container>
 
-                    <ng-container matColumnDef="actions">
-                        <th fxFlex="40" fxLayoutAlign="center center" mat-header-cell *matHeaderCellDef> Actions</th>
-                        <td fxFlex="40" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
-                            <div fxLayout="row" fxFlex="100">
+                        <ng-container matColumnDef="actions">
+                            <th fxFlex="40" fxLayoutAlign="center center" mat-header-cell *matHeaderCellDef> Actions
+                            </th>
+                            <td fxFlex="40" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+                                <div fxLayout="row" fxFlex="100">
                                 <span fxFlex fxFlexOrder="1" fxLayout="row" fxLayoutAlign="center center">
-                                <button mat-button mat-icon-button color="accent"
-                                        (click)="showDashboard(element, false)">
+                                <button mat-button mat-icon-button color="accent" matTooltip="Show data view"
+                                        (click)="showDashboard(element)">
                                     <i class="material-icons">visibility</i>
                                 </button>
                                 </span>
-                                <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center" *ngIf="hasDataExplorerWritePrivileges">
-                                <button mat-button mat-icon-button color="accent"
+                                    <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center"
+                                          *ngIf="hasDataExplorerWritePrivileges">
+                                <button mat-button mat-icon-button color="accent" matTooltip="Edit data view"
                                         [attr.data-cy]="'edit-dashboard-' + element.name"
-                                        (click)="showDashboard(element, true)">
+                                        (click)="editDashboard(element)">
                                     <i class="material-icons">edit</i>
                                 </button>
                                 </span>
-                                <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center" *ngIf="isAdmin">
-                                <button mat-button mat-icon-button color="accent"
+                                    <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center"
+                                          *ngIf="hasDataExplorerWritePrivileges">
+                                <button mat-button mat-icon-button color="accent" matTooltip="Edit data view settings"
+                                        (click)="openEditDataViewDialog(element)">
+                                    <i class="material-icons">settings</i>
+                                </button>
+                                </span>
+                                    <span fxFlex fxFlexOrder="4" fxLayout="row" fxLayoutAlign="center center"
+                                          *ngIf="isAdmin">
+                                <button mat-button mat-icon-button color="accent" matTooltip="Manage permissions"
                                         (click)="showPermissionsDialog(element)">
                                     <i class="material-icons">share</i>
                                 </button>
                                 </span>
-                                <span fxFlex fxFlexOrder="4" fxLayout="row" fxLayoutAlign="center center" *ngIf="hasDataExplorerDeletePrivileges">
-                                <button mat-button mat-icon-button color="accent"
+                                    <span fxFlex fxFlexOrder="5" fxLayout="row" fxLayoutAlign="center center"
+                                          *ngIf="hasDataExplorerDeletePrivileges">
+                                <button mat-button mat-icon-button color="accent" matTooltip="Delete data view"
                                         [attr.data-cy]="'delete-dashboard-' + element.name"
                                         (click)="openDeleteDashboardDialog(element)">
                                     <i class="material-icons">delete</i>
                                 </button>
                                 </span>
-                            </div>
-                        </td>
-                    </ng-container>
+                                </div>
+                            </td>
+                        </ng-container>
 
-                    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
-                    <tr mat-row *matRowDef="let element; columns: displayedColumns;">
-                    </tr>
-                </table>
-            </div>
+                        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                        <tr mat-row *matRowDef="let element; columns: displayedColumns;">
+                        </tr>
+                    </table>
+                </div>
+                <div fxFlex="100"
+                     fxLayout="column"
+                     fxLayoutAlign="center center"
+                     *ngIf="dashboards.length == 0">
+                    <h5>(no data views available)</h5>
+                </div>
+            </sp-basic-inner-panel>
         </div>
     </div>
 
-    <sp-configure-labels *ngIf="editLabels"></sp-configure-labels>
-</div>
+</sp-basic-view>
diff --git a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss
index 25b8b8b..6e728cc 100644
--- a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss
+++ b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss
@@ -25,10 +25,10 @@
 }
 
 .mat-row:nth-child(even) {
-    background-color: var(--color-bg-2);
+    background-color: var(--color-bg-1);
 }
 .mat-row:nth-child(odd) {
-    background-color: var(--color-bg-3);
+    background-color: var(--color-bg-2);
 }
 
 .w-100 {
diff --git a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
index d35d4ad..1e645d9 100644
--- a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
+++ b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
@@ -16,66 +16,80 @@
  *
  */
 
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
 import { MatTableDataSource } from '@angular/material/table';
 import { DataExplorerEditDataViewDialogComponent } from '../../dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component';
-import { DataViewDataExplorerService, Dashboard } from '@streampipes/platform-services';
-import { Tuple2 } from '../../../core-model/base/Tuple2';
-import { DialogService, PanelType } from '@streampipes/shared-ui';
+import { Dashboard, DataViewDataExplorerService } from '@streampipes/platform-services';
+import { DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
 import { ObjectPermissionDialogComponent } from '../../../core-ui/object-permission-dialog/object-permission-dialog.component';
 import { UserRole } from '../../../_enums/user-role.enum';
 import { AuthService } from '../../../services/auth.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
+import { Router } from '@angular/router';
+import { SpDataExplorerRoutes } from '../../data-explorer.routes';
+import { Subscription } from 'rxjs';
 
 @Component({
   selector: 'sp-data-explorer-dashboard-overview',
   templateUrl: './data-explorer-dashboard-overview.component.html',
   styleUrls: ['./data-explorer-dashboard-overview.component.scss']
 })
-export class DataExplorerDashboardOverviewComponent implements OnInit {
+export class DataExplorerDashboardOverviewComponent implements OnInit, OnDestroy {
 
-  @Input() dataViewDashboards: Dashboard[];
-  @Output() reloadDashboardsEmitter = new EventEmitter<void>();
-  @Output() selectDashboardEmitter = new EventEmitter<Tuple2<Dashboard, boolean>>();
 
   dataSource = new MatTableDataSource<Dashboard>();
   displayedColumns: string[] = [];
+  dashboards: Dashboard[] = [];
 
-  editLabels: boolean;
   isAdmin = false;
 
   hasDataExplorerWritePrivileges = false;
   hasDataExplorerDeletePrivileges = false;
 
-  constructor(private dashboardService: DataViewDataExplorerService,
+  authSubscription: Subscription;
+
+  constructor(private dataViewService: DataViewDataExplorerService,
+              private dashboardService: DataViewDataExplorerService,
               public dialogService: DialogService,
-              private authService: AuthService) {
+              private authService: AuthService,
+              private router: Router,
+              private breadcrumbService: SpBreadcrumbService) {
 
   }
 
   ngOnInit(): void {
-    this.authService.user$.subscribe(user => {
+    this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpDataExplorerRoutes.BASE));
+    this.authSubscription = this.authService.user$.subscribe(user => {
       this.hasDataExplorerWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW);
       this.hasDataExplorerDeletePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_DELETE_DATA_EXPLORER_VIEW);
       this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
       this.displayedColumns = ['name', 'actions'];
-
     });
-    this.dataSource.data = this.dataViewDashboards;
-    this.editLabels = false;
+
+    this.getDashboards();
+  }
+
+  ngOnDestroy() {
+    if (this.authSubscription) {
+      this.authSubscription.unsubscribe();
+    }
+  }
+
+  getDashboards() {
+    this.dataViewService.getDataViews().subscribe(data => {
+      this.dashboards = data.sort((a, b) => a.name.localeCompare(b.name));
+      this.dataSource.data = this.dashboards;
+    });
   }
 
   openNewDataViewDialog() {
     const dataViewDashboard: Dashboard = {};
+    dataViewDashboard.dashboardGeneralSettings = {};
     dataViewDashboard.widgets = [];
 
     this.openDataViewModificationDialog(true, dataViewDashboard);
   }
 
-  openEditLabelView() {
-    this.editLabels = true;
-  }
-
   openDataViewModificationDialog(createMode: boolean, dashboard: Dashboard) {
     const dialogRef = this.dialogService.open(DataExplorerEditDataViewDialogComponent, {
       panelType: PanelType.STANDARD_PANEL,
@@ -88,7 +102,7 @@
     });
 
     dialogRef.afterClosed().subscribe(result => {
-      this.reloadDashboardsEmitter.emit();
+      this.getDashboards();
     });
   }
 
@@ -106,7 +120,7 @@
 
     dialogRef.afterClosed().subscribe(refresh => {
       if (refresh) {
-        this.reloadDashboardsEmitter.emit();
+        this.getDashboards();
       }
     });
   }
@@ -116,14 +130,17 @@
   }
 
   openDeleteDashboardDialog(dashboard: Dashboard) {
-    // TODO add confirm dialog
-    this.dashboardService.deleteDashboard(dashboard).subscribe(result => {
-      this.reloadDashboardsEmitter.emit();
+    this.dashboardService.deleteDashboard(dashboard).subscribe(() => {
+      this.getDashboards();
     });
   }
 
-  showDashboard(dashboard: Dashboard, editMode: boolean) {
-    const dashboardSettings: Tuple2<Dashboard, boolean> = { a: dashboard, b: editMode };
-    this.selectDashboardEmitter.emit(dashboardSettings);
+  showDashboard(dashboard: Dashboard) {
+    this.router.navigate(['dataexplorer/', dashboard._id]);
   }
+
+  editDashboard(dashboard: Dashboard) {
+    this.router.navigate(['dataexplorer/', dashboard._id], {queryParams: {action: 'edit'}});
+  }
+
 }
diff --git a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.css b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.css
index 3236d72..3cbc82c 100644
--- a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.css
+++ b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.css
@@ -16,6 +16,19 @@
  *
  */
 
+.fixed-height {
+    height: 50px;
+}
+
+.data-explorer-options {
+    padding:0px;
+}
+
+.data-explorer-options-item {
+    display: inline;
+    margin-right: 10px;
+}
+
 .m-20 {
     margin: 20px;
 }
diff --git a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.html b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.html
index b2c976f..d2108e6 100644
--- a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.html
+++ b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.html
@@ -16,74 +16,162 @@
   ~
   -->
 
-<div class="fixed-height data-explorer-options sp-tab-bg page-container-nav" fxLayout="row" *ngIf="(editMode || timeRangeVisible)">
-    <div class="data-explorer-options-item pl-10" fxLayoutAlign="start center" fxLayout="row" *ngIf="editMode">
-        <button mat-button
-                mat-raised-button
-                color="accent"
-                matTooltip="Save"
-                class="edit-menu-btn"
-                [matTooltipPosition]="'above'"
-                (click)="persistDashboardChanges()"
-                data-cy="save-data-explorer-widget-btn">
-            <mat-icon>save</mat-icon>&nbsp;<span>Save</span>
-        </button>
-        <button mat-button
-                mat-raised-button
-                class="mat-basic mr-10 edit-menu-btn"
-                (click)="discardChanges()">
-            <i class="material-icons">clear</i>
-            <span> Discard</span>
-        </button>
-        <button mat-button
-                mat-raised-button
-                color="accent"
-                class="edit-menu-btn"
-                (click)="createWidget()"
-                [disabled]="!editMode"
-                data-cy="add-new-widget">
-            <i class="material-icons">add</i>
-            <span> Add Widget</span>
-        </button>
-    </div>
-    <div class="data-explorer-options-item" fxLayoutAlign="end center" fxFlex fxLayout="row">
-        <sp-time-range-selector (dateRangeEmitter)="updateDateRange($event)" [dateRange]="timeSettings">
-        </sp-time-range-selector>
-    </div>
-</div>
-
-<div fxFlex="100" fxLayout="column">
-    <mat-drawer-container class="designer-panel-container h-100 dashboard-grid">
-        <mat-drawer #designerDrawer
-                    [opened]="showDesignerPanel"
-                    (opened)="triggerResize()"
-                    (closed)="triggerResize()"
-                    mode="side"
-                    position="end"
-                    class="designer-panel">
-            <div fxLayout="column" fxFlex="100">
-                <sp-data-explorer-designer-panel #designerPanel
-                                                 [currentlyConfiguredWidget]="currentlyConfiguredWidget"
-                                                 [dataLakeMeasure]="dataLakeMeasure"
-                                                 [newWidgetMode]="newWidgetMode"
-                                                 (addWidgetEmitter)="addWidget($event)"
-                                                 (closeDesignerPanelEmitter)="closeDesignerPanel()"
-                                                 fxFlex="100">
-                </sp-data-explorer-designer-panel>
+<div fxLayout="column" class="page-container">
+    <div fxLayout="column" fxFlex="100" *ngIf="dashboardLoaded">
+        <div class="fixed-height data-explorer-options sp-tab-bg page-container-nav" fxLayout="row">
+            <div class="data-explorer-options-item pl-10"
+                 fxLayout="row"
+                 fxLayoutAlign="start center"
+                 style="border-right: 2px solid var(--color-bg-2)">
+                <button mat-button
+                        mat-icon-button
+                        color="accent"
+                        matTooltip="Back"
+                        (click)="goBackToOverview()"
+                        class="edit-menu-btn"
+                        data-cy="save-data-explorer-go-back-to-overview">
+                    <mat-icon>arrow_back</mat-icon>
+                </button>
             </div>
-        </mat-drawer>
-        <mat-drawer-content class="h-100 dashboard-grid">
-            <sp-data-explorer-dashboard-grid
-                #dashboardGrid
-                [editMode]="editMode"
-                [dashboard]="dashboard"
-                [timeSettings]="timeSettings"
-                [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
-                (configureWidgetCallback)="updateCurrentlyConfiguredWidget($event)"
-                (updateCallback)="updateAndQueueItemForDeletion($event)"
-                (deleteCallback)="removeAndQueueItemForDeletion($event)"
-                (startEditModeEmitter)="startEditMode($event)"
-                class="h-100 dashboard-grid"></sp-data-explorer-dashboard-grid>
-        </mat-drawer-content>
-    </mat-drawer-container>
+            <div class="data-explorer-options-item" fxLayoutAlign="start center" fxLayout="row" *ngIf="editMode">
+                <button mat-button mat-icon-button
+                        color="accent"
+                        matTooltip="Save"
+                        class="edit-menu-btn"
+                        (click)="persistDashboardChanges()"
+                        data-cy="save-data-explorer-widget-btn">
+                    <mat-icon>save</mat-icon>
+                </button>
+                <button mat-button
+                        mat-icon-button
+                        color="accent"
+                        matTooltip="Discard"
+                        class="mat-basic mr-10 edit-menu-btn"
+                        (click)="discardChanges()">
+                    <i class="material-icons">undo</i>
+                </button>
+                <button mat-button
+                        mat-icon-button
+                        matTooltip="Add widget"
+                        color="accent"
+                        class="edit-menu-btn" (click)="createWidget()"
+                        [disabled]="!editMode" data-cy="add-new-widget">
+                    <i class="material-icons">add</i>
+                </button>
+            </div>
+            <div class="data-explorer-options-item" fxLayoutAlign="start center" fxLayout="row">
+                <button mat-icon-button
+                        [matMenuTriggerFor]="menu"
+                        aria-label="View mode"
+                        matTooltip="View mode">
+                    <mat-icon>{{viewMode === 'grid' ? 'grid_view' : 'web_asset'}}</mat-icon>
+                </button>
+                <mat-menu #menu="matMenu">
+                    <button mat-menu-item (click)="viewMode = 'grid'">
+                        <mat-icon>grid_view</mat-icon>
+                        <span>Grid</span>
+                    </button>
+                    <button mat-menu-item (click)="viewMode = 'slide'">
+                        <mat-icon>web_asset</mat-icon>
+                        <span>Slides</span>
+                    </button>
+                </mat-menu>
+            </div>
+            <div class="data-explorer-options-item" style="margin-right: 0" fxLayoutAlign="end center" fxFlex
+                 fxLayout="row">
+                <sp-time-range-selector *ngIf="(editMode || timeRangeVisible)"
+                                        (dateRangeEmitter)="updateDateRange($event)" [dateRange]="timeSettings">
+                </sp-time-range-selector>
+
+                <button mat-icon-button [matMenuTriggerFor]="optMenu" aria-label="Options"
+                        data-cy="options-data-explorer">
+                    <mat-icon>more_vert</mat-icon>
+                </button>
+                <mat-menu #optMenu="matMenu">
+                    <button mat-menu-item
+                            (click)="triggerEditMode()"
+                            *ngIf="!editMode && hasDataExplorerWritePrivileges"
+                            data-cy="options-edit-dashboard">
+                        <mat-icon>edit</mat-icon>
+                        <span>Edit dashboard</span>
+                    </button>
+                    <button mat-menu-item
+                            (click)="timeRangeVisible = true"
+                            *ngIf="!editMode && !timeRangeVisible">
+                        <mat-icon>alarm_on</mat-icon>
+                        <span>Show time range selector</span>
+                    </button>
+                    <button mat-menu-item (click)="timeRangeVisible = false" *ngIf="!editMode && timeRangeVisible">
+                        <mat-icon>alarm_off</mat-icon>
+                        <span>Hide time range selector</span>
+                    </button>
+                    <button mat-menu-item *ngIf="hasDataExplorerDeletePrivileges"
+                            (click)="deleteDashboard(dashboard)">
+                        <mat-icon>clear</mat-icon>
+                        <span>Delete dashboard</span>
+                    </button>
+                </mat-menu>
+            </div>
+
+        </div>
+
+        <div fxFlex="100" fxLayout="column">
+            <mat-drawer-container class="designer-panel-container h-100 dashboard-grid">
+                <mat-drawer #designerDrawer
+                            [opened]="showDesignerPanel"
+                            (opened)="triggerResize()"
+                            (closed)="triggerResize()"
+                            mode="side"
+                            position="end"
+                            class="designer-panel">
+                    <div fxLayout="column" fxFlex="100">
+                        <sp-data-explorer-designer-panel #designerPanel
+                                                         [currentlyConfiguredWidget]="currentlyConfiguredWidget"
+                                                         [dataLakeMeasure]="dataLakeMeasure"
+                                                         [newWidgetMode]="newWidgetMode"
+                                                         (addWidgetEmitter)="addWidget($event)"
+                                                         (closeDesignerPanelEmitter)="closeDesignerPanel()"
+                                                         fxFlex="100">
+                        </sp-data-explorer-designer-panel>
+                    </div>
+                </mat-drawer>
+                <mat-drawer-content class="h-100 dashboard-grid">
+                    <div *ngIf="showEditingHelpInfo" fxFlex="100" fxLayout="column" fxLayoutAlign="center center">
+                        <h4>This data view is empty and doesn't contain any widgets.</h4>
+                        <button mat-button
+                                mat-raised-button
+                                color="accent"
+                                *ngIf="hasDataExplorerWritePrivileges"
+                                (click)="triggerEditMode()">
+                            <mat-icon>add</mat-icon>
+                            Add widget
+                        </button>
+                    </div>
+                    <sp-data-explorer-dashboard-grid #dashboardGrid
+                                                     *ngIf="!showEditingHelpInfo && viewMode === 'grid'"
+                                                     [editMode]="editMode"
+                                                     [dashboard]="dashboard"
+                                                     [timeSettings]="timeSettings"
+                                                     [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
+                                                     (configureWidgetCallback)="updateCurrentlyConfiguredWidget($event)"
+                                                     (updateCallback)="updateAndQueueItemForDeletion($event)"
+                                                     (deleteCallback)="removeAndQueueItemForDeletion($event)"
+                                                     (startEditModeEmitter)="startEditMode($event)"
+                                                     class="h-100 dashboard-grid">
+                    </sp-data-explorer-dashboard-grid>
+                    <sp-data-explorer-dashboard-slide-view class="h-100 dashboard-grid" #dashboardSlide
+                                                           [editMode]="editMode"
+                                                           [dashboard]="dashboard"
+                                                           [timeSettings]="timeSettings"
+                                                           [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
+                                                           (configureWidgetCallback)="updateCurrentlyConfiguredWidget($event)"
+                                                           (updateCallback)="updateAndQueueItemForDeletion($event)"
+                                                           (deleteCallback)="removeAndQueueItemForDeletion($event)"
+                                                           (startEditModeEmitter)="startEditMode($event)"
+                                                           *ngIf="!showEditingHelpInfo && viewMode === 'slide'">
+                    </sp-data-explorer-dashboard-slide-view>
+                </mat-drawer-content>
+            </mat-drawer-container>
+        </div>
+    </div>
 </div>
diff --git a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts
index 3e214d9..f03b006 100644
--- a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts
+++ b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts
@@ -16,47 +16,65 @@
  *
  */
 
-import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
-import { Observable, zip } from 'rxjs';
-import { RefreshDashboardService } from '../../services/refresh-dashboard.service';
-import { DataExplorerDashboardGridComponent } from '../grid/data-explorer-dashboard-grid.component';
+import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild, } from '@angular/core';
+import { Observable, of, Subscription, zip } from 'rxjs';
+import { DataExplorerDashboardGridComponent } from '../widget-view/grid-view/data-explorer-dashboard-grid.component';
 import { MatDrawer } from '@angular/material/sidenav';
 import { Tuple2 } from '../../../core-model/base/Tuple2';
 import {
+  ClientDashboardItem,
   Dashboard,
-  TimeSettings,
   DataExplorerWidgetModel,
   DataLakeMeasure,
-  ClientDashboardItem,
-  DataViewDataExplorerService
+  DataViewDataExplorerService,
+  TimeSettings,
 } from '@streampipes/platform-services';
 import { DataExplorerDesignerPanelComponent } from '../designer-panel/data-explorer-designer-panel.component';
 import { TimeSelectionService } from '../../services/time-selection.service';
+import { AuthService } from '../../../services/auth.service';
+import { UserPrivilege } from '../../../_enums/user-privilege.enum';
+import { ActivatedRoute, ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
+import { DataExplorerDashboardSlideViewComponent } from '../widget-view/slide-view/data-explorer-dashboard-slide-view.component';
+import { ConfirmDialogComponent, SpBreadcrumbService } from '@streampipes/shared-ui';
+import { MatDialog } from '@angular/material/dialog';
+import { map } from 'rxjs/operators';
+import { SpDataExplorerRoutes } from '../../data-explorer.routes';
 
 @Component({
   selector: 'sp-data-explorer-dashboard-panel',
   templateUrl: './data-explorer-dashboard-panel.component.html',
-  styleUrls: ['./data-explorer-dashboard-panel.component.css']
+  styleUrls: ['./data-explorer-dashboard-panel.component.css'],
 })
-export class DataExplorerDashboardPanelComponent implements OnInit {
-
-  @Input() dashboard: Dashboard;
+export class DataExplorerDashboardPanelComponent implements OnInit, OnDestroy {
+  dashboardLoaded = false;
+  dashboard: Dashboard;
 
   /**
    * This is the date range (start, end) to view the data and is set in data-explorer.ts
    */
-  @Input() timeSettings: TimeSettings;
-  @Input() editMode: boolean;
-  @Input() timeRangeVisible: boolean;
+  timeSettings: TimeSettings;
+  viewMode = 'grid';
 
-  @Output() editModeChange: EventEmitter<boolean> = new EventEmitter();
+  editMode = false;
+  timeRangeVisible = true;
 
-  @Output() resetDashboardChanges: EventEmitter<boolean> = new EventEmitter();
+  @Output()
+  editModeChange: EventEmitter<boolean> = new EventEmitter();
 
-  @ViewChild('dashboardGrid') dashboardGrid: DataExplorerDashboardGridComponent;
-  @ViewChild('designerDrawer') designerDrawer: MatDrawer;
-  @ViewChild('designerPanel') designerPanel: DataExplorerDesignerPanelComponent;
+  @ViewChild('dashboardGrid')
+  dashboardGrid: DataExplorerDashboardGridComponent;
+
+  @ViewChild('dashboardSlide')
+  dashboardSlide: DataExplorerDashboardSlideViewComponent;
+
+  @ViewChild('designerDrawer')
+  designerDrawer: MatDrawer;
+
+  @ViewChild('designerPanel')
+  designerPanel: DataExplorerDesignerPanelComponent;
+
+  hasDataExplorerWritePrivileges = false;
+  hasDataExplorerDeletePrivileges = false;
 
   public items: Dashboard[];
 
@@ -69,25 +87,65 @@
   dataLakeMeasure: DataLakeMeasure;
 
   showDesignerPanel = false;
+  showEditingHelpInfo = false;
 
-  constructor(private dataViewDataExplorerService: DataViewDataExplorerService,
-              public dialog: MatDialog,
-              private refreshDashboardService: RefreshDashboardService,
-              private timeSelectionService: TimeSelectionService) {
+  authSubscription: Subscription;
+
+  constructor(
+    private dataViewDataExplorerService: DataViewDataExplorerService,
+    private dialog: MatDialog,
+    private timeSelectionService: TimeSelectionService,
+    private authService: AuthService,
+    private dashboardService: DataViewDataExplorerService,
+    private route: ActivatedRoute,
+    private dataViewService: DataViewDataExplorerService,
+    private router: Router,
+    private breadcrumbService: SpBreadcrumbService) {
   }
 
   public ngOnInit() {
+
+    const params = this.route.snapshot.params;
+    const queryParams = this.route.snapshot.queryParams;
+
+    const startTime = params.startTime;
+    const endTime = params.endTime;
+
+    this.getDashboard(params.id, startTime, endTime);
+
+
+    this.authSubscription = this.authService.user$.subscribe(user => {
+      this.hasDataExplorerWritePrivileges = this.authService.hasRole(
+        UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW
+      );
+      this.hasDataExplorerDeletePrivileges = this.authService.hasRole(
+        UserPrivilege.PRIVILEGE_DELETE_DATA_EXPLORER_VIEW
+      );
+      if (queryParams.action === 'edit' && this.hasDataExplorerWritePrivileges) {
+        this.editMode = true;
+      }
+    });
+  }
+
+  ngOnDestroy() {
+    if (this.authSubscription) {
+      this.authSubscription.unsubscribe();
+    }
   }
 
   triggerResize() {
     window.dispatchEvent(new Event('resize'));
   }
 
-  addWidget(widgetConfig: Tuple2<DataLakeMeasure, DataExplorerWidgetModel>): void {
+  addWidget(
+    widgetConfig: Tuple2<DataLakeMeasure, DataExplorerWidgetModel>
+  ): void {
     this.dataLakeMeasure = widgetConfig.a;
-    this.dataViewDataExplorerService.saveWidget(widgetConfig.b).subscribe(response => {
-      this.addWidgetToDashboard(response);
-    });
+    this.dataViewDataExplorerService
+      .saveWidget(widgetConfig.b)
+      .subscribe((response) => {
+        this.addWidgetToDashboard(response);
+      });
   }
 
   addWidgetToDashboard(widget: DataExplorerWidgetModel) {
@@ -99,37 +157,54 @@
     dashboardItem.x = 0;
     dashboardItem.y = 0;
     this.dashboard.widgets.push(dashboardItem);
-    this.dashboardGrid.loadWidgetConfig(widget._id, true);
+    if (this.viewMode === 'grid') {
+      this.dashboardGrid.loadWidgetConfig(widget._id, true);
+    } else {
+      this.dashboardSlide.loadWidgetConfig(widget._id, true);
+    }
   }
 
   persistDashboardChanges() {
-    this.dataViewDataExplorerService.updateDashboard(this.dashboard).subscribe(result => {
-      this.dashboard._rev = result._rev;
-      if (this.widgetIdsToRemove.length > 0) {
-        const observables = this.deleteWidgets();
-        zip(...observables).subscribe(() => {
-          this.widgetIdsToRemove.forEach(id => {
-            this.dashboardGrid.configuredWidgets.delete(id);
+    this.dataViewDataExplorerService
+      .updateDashboard(this.dashboard)
+      .subscribe((result) => {
+        this.dashboard._rev = result._rev;
+        if (this.widgetIdsToRemove.length > 0) {
+          const observables = this.deleteWidgets();
+          zip(...observables).subscribe(() => {
+            this.widgetIdsToRemove.forEach((id) => {
+              if (this.viewMode === 'grid') {
+                this.dashboardGrid.configuredWidgets.delete(id);
+              } else {
+                this.dashboardSlide.configuredWidgets.delete(id);
+              }
+            });
+
+            this.afterDashboardChange();
           });
-
+        } else {
           this.afterDashboardChange();
-        });
-      } else {
-        this.afterDashboardChange();
-      }
+        }
+      });
 
-    });
+    this.editMode = false;
   }
 
   afterDashboardChange() {
-    this.dashboardGrid.updateAllWidgets();
+    if (this.viewMode === 'grid') {
+      this.dashboardGrid.updateAllWidgets();
+    } else {
+      this.dashboardSlide.updateAllWidgets();
+    }
     this.editModeChange.emit(false);
     this.closeDesignerPanel();
   }
 
   startEditMode(widgetModel: DataExplorerWidgetModel) {
+    this.editMode = true;
     this.editModeChange.emit(true);
     this.updateCurrentlyConfiguredWidget(widgetModel);
+    this.showEditingHelpInfo = false;
   }
 
   prepareWidgetUpdates(): Observable<any>[] {
@@ -142,7 +217,9 @@
   }
 
   removeAndQueueItemForDeletion(widget: DataExplorerWidgetModel) {
-    const index = this.dashboard.widgets.findIndex(item => item.id === widget._id);
+    const index = this.dashboard.widgets.findIndex(
+      (item) => item.id === widget._id
+    );
     this.dashboard.widgets.splice(index, 1);
     this.widgetIdsToRemove.push(widget._id);
     if (this.currentlyConfiguredWidget._id === widget._id) {
@@ -155,7 +232,7 @@
   }
 
   deleteWidgets(): Observable<any>[] {
-    return this.widgetIdsToRemove.map(widgetId => {
+    return this.widgetIdsToRemove.map((widgetId) => {
       return this.dataViewDataExplorerService.deleteWidget(widgetId);
     });
   }
@@ -180,26 +257,37 @@
     } else {
       this.showDesignerPanel = false;
     }
-
   }
 
   discardChanges() {
-    this.resetDashboardChanges.emit(true);
+    this.editMode = false;
+  }
+
+  triggerEditMode() {
+    this.showEditingHelpInfo = false;
+    this.editMode = true;
+    this.editModeChange.emit(true);
+    this.createWidget();
   }
 
   createWidget() {
     this.dataLakeMeasure = new DataLakeMeasure();
     this.currentlyConfiguredWidget = new DataExplorerWidgetModel();
-    this.currentlyConfiguredWidget['@class'] = 'org.apache.streampipes.model.datalake.DataExplorerWidgetModel';
+    this.currentlyConfiguredWidget['@class'] =
+      'org.apache.streampipes.model.datalake.DataExplorerWidgetModel';
     this.currentlyConfiguredWidget.baseAppearanceConfig = {};
-    this.currentlyConfiguredWidget.baseAppearanceConfig.widgetTitle = 'New Widget';
+    this.currentlyConfiguredWidget.baseAppearanceConfig.widgetTitle =
+      'New Widget';
     this.currentlyConfiguredWidget.dataConfig = {};
-    this.currentlyConfiguredWidget.baseAppearanceConfig.backgroundColor = '#FFFFFF';
+    this.currentlyConfiguredWidget.baseAppearanceConfig.backgroundColor =
+      '#FFFFFF';
     this.currentlyConfiguredWidget.baseAppearanceConfig.textColor = '#3e3e3e';
     this.newWidgetMode = true;
     this.showDesignerPanel = true;
     this.newWidgetMode = true;
-    this.designerPanel.resetIndex();
+    if (this.designerPanel) {
+      this.designerPanel.resetIndex();
+    }
   }
 
   closeDesignerPanel() {
@@ -208,4 +296,62 @@
     this.dataLakeMeasure = undefined;
     this.currentlyConfiguredWidgetId = undefined;
   }
+
+  deleteDashboard(dashboard: Dashboard) {
+    this.dashboardService.deleteDashboard(dashboard).subscribe((result) => {
+      this.goBackToOverview();
+    });
+  }
+
+  getDashboard(dashboardId: string,
+               startTime: number,
+               endTime: number) {
+    this.dataViewService.getDataViews().subscribe((data) => {
+      this.dashboard = data.filter(
+        (dashboard) => dashboard._id === dashboardId
+      )[0];
+      this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.makeRoute([SpDataExplorerRoutes.BASE], this.dashboard.name));
+      this.viewMode = this.dashboard.dashboardGeneralSettings.defaultViewMode || 'grid';
+      this.timeSettings = (startTime && endTime) ? this.overrideTime(+startTime, +endTime) : this.dashboard.dashboardTimeSettings;
+      if (this.dashboard.widgets.length === 0 && this.editMode) {
+        this.triggerEditMode();
+      } else if (this.dashboard.widgets.length === 0 && !(this.editMode)) {
+        this.showEditingHelpInfo = true;
+      }
+      this.dashboardLoaded = true;
+    });
+  }
+
+  overrideTime(startTime: number,
+               endTime: number): TimeSettings {
+    return {startTime, endTime, dynamicSelection: -1};
+  }
+
+  goBackToOverview() {
+    this.router.navigate(['dataexplorer']);
+  }
+
+  confirmLeaveDashboard(route: ActivatedRouteSnapshot,
+                        state: RouterStateSnapshot): Observable<boolean> {
+    if (this.editMode) {
+      const dialogRef = this.dialog.open(ConfirmDialogComponent, {
+        width: '500px',
+        data: {
+          'title': 'Save changes?',
+          'subtitle': 'Update all changes to dashboard widgets or discard current changes.',
+          'cancelTitle': 'Discard changes',
+          'okTitle': 'Update',
+          'confirmAndCancel': true
+        },
+      });
+      return dialogRef.afterClosed().pipe(map(shouldUpdate => {
+        if (shouldUpdate) {
+          this.persistDashboardChanges();
+        }
+        return true;
+      }));
+    } else {
+      return of(true);
+    }
+  }
 }
diff --git a/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.html b/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.html
index 492a18d..a7feeac 100644
--- a/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.html
+++ b/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.html
@@ -22,7 +22,7 @@
                 *ngFor="let item of possibleTimeButtons"
                 [color]="selectedTimeButton.value === item.value ? 'accent' : ''"
                 [attr.data-cy]="item.value.replace(' ', '_')"
-                class="button-margin smaller-button-font-size"
+                [ngClass]="'button-margin smaller-button-font-size'"
                 (click)="this.setCurrentDateRange(item)">{{item.value}}</button>
     </div>
     <div class="time-wrapper" fxFlex fxLayoutAlign="center center">
diff --git a/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.scss b/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.scss
index 4768cb9..eeb2dd6 100644
--- a/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.scss
+++ b/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.scss
@@ -31,14 +31,14 @@
 }
 
 .button-margin {
-    border-radius: 0;
-    padding-left: 4px;
-    padding-right:4px;
-    border-right: 1px solid #cccccc;
+    border-radius: 0 !important;
+    padding-left: 4px !important;
+    padding-right:4px !important;
+    border-right: 1px solid #cccccc !important;
 }
 
 .button-margin:last-of-type {
-    border-right: 0;
+    border-right: 0 !important;
 }
 
 .time-range-wrapper {
diff --git a/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.ts b/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.ts
index 3891683..da92eb2 100644
--- a/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.ts
+++ b/ui/src/app/data-explorer/components/time-selector/timeRangeSelector.component.ts
@@ -54,6 +54,9 @@
       this.setCurrentDateRange(this.possibleTimeButtons[0]);
     } else if (this.dateRange.dynamicSelection !== -1) {
       this.setCurrentDateRange(this.possibleTimeButtons.find(tb => tb.offset === this.dateRange.dynamicSelection));
+    } else {
+      this.startDate = new Date(this._dateRange.startTime);
+      this.endDate = new Date(this._dateRange.endTime);
     }
   }
 
diff --git a/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts b/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts
new file mode 100644
index 0000000..a05811b
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Directive, EventEmitter, Input, Output } from '@angular/core';
+import {
+  Dashboard,
+  DataExplorerWidgetModel,
+  DataLakeMeasure,
+  DataViewDataExplorerService,
+  TimeSettings
+} from '@streampipes/platform-services';
+import { ResizeService } from '../../services/resize.service';
+import { zip } from 'rxjs';
+
+@Directive()
+export abstract class AbstractWidgetViewDirective {
+
+  _dashboard: Dashboard;
+
+  @Input()
+  editMode: boolean;
+
+  @Input()
+  currentlyConfiguredWidgetId: string;
+
+  configuredWidgets: Map<string, DataExplorerWidgetModel> = new Map<string, DataExplorerWidgetModel>();
+  dataLakeMeasures: Map<string, DataLakeMeasure> = new Map<string, DataLakeMeasure>();
+
+  widgetsAvailable = false;
+  widgetsVisible = true;
+
+  /**
+   * This is the date range (start, end) to view the data and is set in data-explorer.ts
+   */
+  @Input()
+  timeSettings: TimeSettings;
+
+  @Output() deleteCallback: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
+  @Output() updateCallback: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
+  @Output() configureWidgetCallback: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
+  @Output() startEditModeEmitter: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
+
+
+  constructor(protected resizeService: ResizeService,
+              protected dataViewDataExplorerService: DataViewDataExplorerService) {
+
+  }
+
+  updateAllWidgets() {
+    this.configuredWidgets.forEach((value, key) => {
+      this.dataViewDataExplorerService.updateWidget(value).subscribe(response => {
+        value._rev = response._rev;
+        this.currentlyConfiguredWidgetId = undefined;
+      });
+    });
+  }
+
+  startEditMode(value: DataExplorerWidgetModel) {
+    this.startEditModeEmitter.emit(value);
+    this.currentlyConfiguredWidgetId = value._id;
+  }
+
+  @Input() set dashboard(dashboard: Dashboard) {
+    this._dashboard = dashboard;
+    this.loadWidgetConfigs();
+  }
+
+  get dashboard() {
+    return this._dashboard;
+  }
+
+  loadWidgetConfigs() {
+    const observables = this.dashboard.widgets.map(w => this.dataViewDataExplorerService.getWidget(w.id));
+    zip(...observables).subscribe(results => {
+      results.forEach(r => {
+        this.processWidget(r);
+        this.onWidgetsAvailable();
+        this.widgetsAvailable = true;
+        if (this.dashboard.widgets.length > 0 && this.editMode) {
+          this.startEditModeEmitter.emit(this.configuredWidgets.get(this.dashboard.widgets[0].id));
+        }
+      });
+    });
+  }
+
+  loadWidgetConfig(widgetId: string, setCurrentlyConfigured?: boolean) {
+    if (!this.isGridView()) {
+      this.widgetsVisible = false;
+    }
+    this.dataViewDataExplorerService.getWidget(widgetId).subscribe(response => {
+      this.processWidget(response);
+      if (setCurrentlyConfigured) {
+        this.propagateWidgetSelection(this.configuredWidgets.get(widgetId));
+        if (!this.isGridView()) {
+          this.selectNewWidget(widgetId);
+        }
+      }
+      if (!this.isGridView()) {
+        this.widgetsVisible = true;
+      }
+      this.widgetsAvailable = true;
+    });
+  }
+
+  processWidget(widget: DataExplorerWidgetModel) {
+    this.configuredWidgets.set(widget._id, widget);
+    this.dataLakeMeasures.set(widget._id, widget.dataConfig.sourceConfigs[0].measure);
+  }
+
+  propagateItemRemoval(widget: DataExplorerWidgetModel) {
+    this.deleteCallback.emit(widget);
+  }
+
+  propagateItemUpdate(dashboardWidget: DataExplorerWidgetModel) {
+    this.updateCallback.emit(dashboardWidget);
+  }
+
+  propagateWidgetSelection(configuredWidget: DataExplorerWidgetModel) {
+    this.configureWidgetCallback.emit(configuredWidget);
+    if (configuredWidget) {
+      this.currentlyConfiguredWidgetId = configuredWidget._id;
+    } else {
+      this.currentlyConfiguredWidgetId = undefined;
+    }
+    this.onOptionsChanged();
+  }
+
+  abstract onOptionsChanged(): void;
+
+  abstract onWidgetsAvailable(): void;
+
+  abstract isGridView(): boolean;
+
+  abstract selectNewWidget(widgetId): void;
+
+
+
+}
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
similarity index 89%
rename from ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html
rename to ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
index 31fea68..5afe663 100644
--- a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html
+++ b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
@@ -24,6 +24,7 @@
     <ng-container *ngFor="let item of dashboard.widgets;let i=index">
         <gridster-item [item]="item" #gridsterItemComponent class="shadow">
             <sp-data-explorer-dashboard-widget
+                    [ngStyle]="{height: gridsterItemComponent.height -13 + 'px'}"
                     [timeSettings]="timeSettings"
                     (updateCallback)="propagateItemUpdate($event)"
                     (deleteCallback)="propagateItemRemoval($event)"
@@ -34,8 +35,9 @@
                     [dataLakeMeasure]="dataLakeMeasures.get(item.id)"
                     [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
                     [editMode]="editMode"
+                    [gridMode]="true"
                     [gridsterItemComponent]="gridsterItemComponent"
-                    *ngIf="configuredWidgets.has(item.id) && dataLakeMeasures.has(item.id)"></sp-data-explorer-dashboard-widget>
+                    *ngIf="widgetsAvailable && configuredWidgets.has(item.id)"></sp-data-explorer-dashboard-widget>
         </gridster-item>
     </ng-container>
 </gridster>
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.scss b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.scss
rename to ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.scss
diff --git a/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.ts b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.ts
new file mode 100644
index 0000000..ccd179c
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.ts
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnChanges, OnInit, QueryList, SimpleChanges, ViewChildren } from '@angular/core';
+import { GridsterItemComponent, GridType } from 'angular-gridster2';
+import { GridsterInfo } from '../../../../dashboard/models/gridster-info.model';
+import { IDataViewDashboardConfig } from '../../../models/dataview-dashboard.model';
+import { ResizeService } from '../../../services/resize.service';
+import { DataViewDataExplorerService } from '@streampipes/platform-services';
+import { AbstractWidgetViewDirective } from '../abstract-widget-view.directive';
+
+@Component({
+  selector: 'sp-data-explorer-dashboard-grid',
+  templateUrl: './data-explorer-dashboard-grid.component.html',
+  styleUrls: ['./data-explorer-dashboard-grid.component.scss']
+})
+export class DataExplorerDashboardGridComponent extends AbstractWidgetViewDirective implements OnInit, OnChanges {
+
+  options: IDataViewDashboardConfig;
+  loaded = false;
+
+  @ViewChildren(GridsterItemComponent) gridsterItemComponents: QueryList<GridsterItemComponent>;
+
+  constructor(protected resizeService: ResizeService,
+              protected dataViewDataExplorerService: DataViewDataExplorerService) {
+    super(resizeService, dataViewDataExplorerService);
+  }
+
+  ngOnInit(): void {
+    this.options = {
+      disablePushOnDrag: true,
+      draggable: {enabled: this.editMode},
+      gridType: GridType.VerticalFixed,
+      minCols: 8,
+      maxCols: 8,
+      minRows: 4,
+      fixedRowHeight: 100,
+      fixedColWidth: 100,
+      margin: 5,
+      displayGrid: this.editMode ? 'always' : 'none',
+      resizable: {enabled: this.editMode},
+      itemResizeCallback: ((item, itemComponent) => {
+        this.resizeService.notify({
+          gridsterItem: item,
+          gridsterItemComponent: itemComponent
+        } as GridsterInfo);
+      }),
+      itemInitCallback: ((item, itemComponent) => {
+        this.resizeService.notify({
+          gridsterItem: item,
+          gridsterItemComponent: itemComponent
+        } as GridsterInfo);
+        window.dispatchEvent(new Event('resize'));
+      })
+    };
+  }
+
+  ngOnChanges(changes: SimpleChanges): void {
+    if (changes['editMode'] && this.options) {
+      this.options.draggable.enabled = this.editMode;
+      this.options.resizable.enabled = this.editMode;
+      this.options.displayGrid = this.editMode ? 'always' : 'none';
+      this.options.api.optionsChanged();
+    }
+  }
+
+  toggleGrid() {
+    this.options.displayGrid = this.options.displayGrid === 'none' ? 'always' : 'none';
+    this.options.api.optionsChanged();
+  }
+
+  onOptionsChanged() {
+    this.options.api.optionsChanged();
+  }
+
+  onWidgetsAvailable(): void {
+  }
+
+  isGridView(): boolean {
+    return true;
+  }
+
+  selectNewWidget(widgetId): void {
+  }
+
+}
diff --git a/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.html b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.html
new file mode 100644
index 0000000..df87da3
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.html
@@ -0,0 +1,55 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column" style="overflow-y:hidden">
+  <div class="h-100" fxLayout="row" fxFlex="100">
+    <div fxFlex="200px"
+         fxLayout="column"
+         class="selection-box" *ngIf="widgetsAvailable && currentWidget">
+      <div *ngFor="let item of dashboard.widgets; let i = index"
+           [ngClass]="item.id === currentWidget._id ? 'viz-preview viz-preview-selected' : 'viz-preview'"
+           fxLayoutAlign="center center"
+           (click)="selectWidget(i, item.id)">
+        <div fxFlex="100"
+             fxLayout="column"
+             fxLayoutAlign="center center">
+          <span class="slide-view-title" *ngIf="widgetsVisible">{{configuredWidgets.get(item.id).baseAppearanceConfig.widgetTitle}}</span>
+        </div>
+      </div>
+    </div>
+    <div fxFlex="100">
+      <div class="h-100 w-100 mw-100" id="slideViewOuter" fxFlex="100">
+                <sp-data-explorer-dashboard-widget
+                        [ngStyle]="{height: gridsterItemComponent.height -15 + 'px'}"
+                        [timeSettings]="timeSettings"
+                        (updateCallback)="propagateItemUpdate($event)"
+                        (deleteCallback)="propagateItemRemoval($event)"
+                        (configureWidgetCallback)="propagateWidgetSelection($event)"
+                        (startEditModeEmitter)="startEditMode($event)"
+                        [dashboardItem]="currentDashboardItem"
+                        [configuredWidget]="currentWidget"
+                        [dataLakeMeasure]="currentMeasure"
+                        [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
+                        [editMode]="editMode"
+                        [gridMode]="false"
+                        [gridsterItemComponent]="gridsterItemComponent"
+                        *ngIf="widgetsAvailable && displayWidget && currentWidget && widgetsVisible"></sp-data-explorer-dashboard-widget>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.scss
similarity index 66%
copy from ui/src/app/connect/components/format-item-json/format-item-json.component.scss
copy to ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.scss
index 30123c0..8203bd3 100644
--- a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
+++ b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.scss
@@ -16,32 +16,33 @@
  *
  */
 
-
-.format-label {
-  line-height:50px;
-  margin: auto;
-  text-align: center;
-  font-weight: bold;
-  font-size: 1.3em;
-}
-
-.format-box {
-  min-height: 50px;
-  box-shadow: 1px 1px 2px #555;
-  border: 1px solid gray;
+.viz-preview {
+  height: 100px;
+  min-height: 100px;
+  border: 1px solid var(--color-bg-2);
   cursor: pointer;
-  padding: 10px;
-  opacity: 0.7;
-  margin: 10px;
-  background: #ffffff;
+  margin: 5px 10px;
+  padding: 5px;
 }
 
-.format-box:hover {
-  opacity: 1;
+.viz-preview-selected {
+  border: 3px solid var(--color-accent);
 }
 
-.selectedItem {
-  opacity: 1;
-  background-color: grey;
+.selection-box {
+  overflow-y: auto;
+  overflow-x: hidden;
+  margin-bottom: 5px;
+  height: calc(100vh - 147px);
+  max-width: 100%;
 }
 
+.slide-view-title {
+  text-align: center;
+  font-size: 10pt;
+}
+
+.mw-100 {
+  max-width: 100%;
+  overflow-x: hidden;
+}
diff --git a/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.ts b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.ts
new file mode 100644
index 0000000..e272c70
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.ts
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { AfterViewInit, Component, ElementRef, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
+import { AbstractWidgetViewDirective } from '../abstract-widget-view.directive';
+import { ResizeService } from '../../../services/resize.service';
+import {
+  DashboardItem,
+  DataExplorerWidgetModel,
+  DataLakeMeasure,
+  DataViewDataExplorerService
+} from '@streampipes/platform-services';
+
+@Component({
+  selector: 'sp-data-explorer-dashboard-slide-view',
+  templateUrl: './data-explorer-dashboard-slide-view.component.html',
+  styleUrls: ['./data-explorer-dashboard-slide-view.component.scss']
+})
+export class DataExplorerDashboardSlideViewComponent extends AbstractWidgetViewDirective implements OnInit, AfterViewInit, OnChanges {
+
+  selectedWidgetIndex = 0;
+
+  gridsterItemComponent: any = {width: 100, height: 100};
+  previewGridsterItemComponent: any = {width: 200, height: 100};
+
+  currentWidget: DataExplorerWidgetModel;
+  currentMeasure: DataLakeMeasure;
+  currentDashboardItem: DashboardItem;
+
+  displayWidget = false;
+
+  @ViewChild('slideViewOuter') slideViewOuter: ElementRef;
+
+  constructor(protected resizeService: ResizeService,
+              protected dataViewDataExplorerService: DataViewDataExplorerService) {
+    super(resizeService, dataViewDataExplorerService);
+  }
+
+  ngOnChanges(changes: SimpleChanges): void {
+  }
+
+  ngOnInit(): void {
+  }
+
+
+  onOptionsChanged(): void {
+  }
+
+  selectWidget(index: number,
+               widgetId: string): void {
+    this.displayWidget = false;
+    setTimeout(() => {
+      this.selectedWidgetIndex = index;
+      this.currentWidget = this.configuredWidgets.get(widgetId);
+      this.currentMeasure = this.dataLakeMeasures.get(widgetId);
+      this.currentDashboardItem = this.dashboard.widgets[index] as unknown as DashboardItem;
+      this.currentlyConfiguredWidgetId = widgetId;
+
+      // Opens the design panel for the current widget when in edit mode 
+      if (this.editMode) {
+        this.startEditModeEmitter.emit(this.currentWidget);
+      }
+
+      this.displayWidget = true;
+    });
+
+  }
+
+  ngAfterViewInit(): void {
+    const obs = new ResizeObserver(entries => {
+      entries.forEach(entry => {
+        const cr = entry.contentRect;
+        this.gridsterItemComponent.width = cr.width;
+        this.gridsterItemComponent.height = cr.height;
+        this.resizeService.notify({
+          gridsterItem: this.dashboard.widgets[this.selectedWidgetIndex],
+          gridsterItemComponent: this.gridsterItemComponent
+        });
+      });
+    });
+    obs.observe(document.getElementById('slideViewOuter'));
+
+  }
+
+  onWidgetsAvailable(): void {
+    this.selectWidget(0, this.dashboard.widgets[0].id);
+  }
+
+  isGridView(): boolean {
+    return false;
+  }
+
+  selectNewWidget(widgetId): void {
+    this.selectWidget(this.dashboard.widgets.length - 1, widgetId);
+  }
+
+}
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
index f6c3d61..8c4b4b5 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
@@ -16,73 +16,83 @@
   ~
   -->
 
-<div class="h-100 shadow">
-    <div class="box"
-         [ngStyle]='{background: configuredWidget.baseAppearanceConfig.backgroundColor,
+<div class="h-100">
+  <div class="box"
+       [ngStyle]="{background: configuredWidget.baseAppearanceConfig.backgroundColor,
          color: configuredWidget.baseAppearanceConfig.textColor,
-         border: currentlyConfiguredWidgetId === configuredWidget._id ? "2px solid var(--color-accent)" : "2px solid " + configuredWidget.baseAppearanceConfig.backgroundColor}'
-         [attr.data-cy]="'widget-' + configuredWidget.baseAppearanceConfig.widgetTitle">
-        <div class="widget-header h-40">
-            <div fxFlex="100" fxLayout="row" fxLayoutAlign="start center" class="widget-header-text">
-                {{ configuredWidget.baseAppearanceConfig.widgetTitle }}
-            </div>
-            <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
-                <div class="time-counter"
-                     *ngIf="editMode"
-                     [ngStyle]="{background: configuredWidget.baseAppearanceConfig.textColor, color: configuredWidget.baseAppearanceConfig.backgroundColor}">
-                    {{loadingTime}}s
-                </div>
-                <button mat-button
-                        mat-icon-button
-                        [matMenuTriggerFor]="menu"
-                        aria-label="More options"
-                        matTooltip="More options"
-                        *ngIf="!editMode"
-                        [attr.data-cy]="'more-options-' + configuredWidget.baseAppearanceConfig.widgetTitle">
-                    <mat-icon>more_vert</mat-icon>
-                </button>
-                <mat-menu #menu="matMenu">
-                    <button mat-menu-item
-                            (click)="downloadDataAsFile()">
-                        <mat-icon>get_app</mat-icon>
-                        <span>Download data</span>
-                    </button>
-                    <button mat-menu-item
-                            (click)="startEditMode()"
-                            *ngIf="hasDataExplorerWritePrivileges"
-                            [attr.data-cy]="'start-edit-' + configuredWidget.baseAppearanceConfig.widgetTitle">
-                        <mat-icon>edit</mat-icon>
-                        <span>Edit Widget</span>
-                    </button>
-                </mat-menu>
-                <button mat-button
-                        mat-icon-button
-                        *ngIf="editMode"
-                        (click)="downloadDataAsFile()">
-                    <mat-icon>get_app</mat-icon>
-                </button>
-                <button mat-button
-                        mat-icon-button
-                        [class.mat-raised-button]="currentlyConfiguredWidgetId === configuredWidget._id"
-                        (click)="triggerWidgetEditMode()"
-                        *ngIf="editMode"
-                        [color]="currentlyConfiguredWidgetId === configuredWidget._id ? 'accent' : ''"
-                        matTooltip="Edit widget"
-                        [attr.data-cy]="'edit-' + configuredWidget.baseAppearanceConfig.widgetTitle">
-                    <mat-icon>edit</mat-icon>
-                </button>
-                <button mat-button
-                        mat-icon-button
-                        (click)="removeWidget()"
-                        matTooltip="Delete widget"
-                        *ngIf="editMode && hasDataExplorerDeletePrivileges"
-                        [attr.data-cy]="'remove-' + configuredWidget.baseAppearanceConfig.widgetTitle">
-                    <mat-icon>clear</mat-icon>
-                </button>
-            </div>
+         height: (gridsterItemComponent.height - 13) + 'px',
+         border: editMode && currentlyConfiguredWidgetId === configuredWidget._id ? '4px solid var(--color-accent)' : '2px solid ' + configuredWidget.baseAppearanceConfig.backgroundColor}"
+       [attr.data-cy]="'widget-' + configuredWidget.baseAppearanceConfig.widgetTitle">
+    <div class="widget-header h-40" *ngIf="!previewMode">
+      <div fxFlex="100" fxLayout="row" fxLayoutAlign="start center" class="widget-header-text">
+        {{ configuredWidget.baseAppearanceConfig.widgetTitle }}
+      </div>
+      <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
+        <mat-spinner [diameter]="20" color="primary" class="mr-10" *ngIf="timerActive">
+        </mat-spinner>
+        <div class="time-counter"
+             *ngIf="editMode"
+             [ngStyle]="{background: configuredWidget.baseAppearanceConfig.textColor, color: configuredWidget.baseAppearanceConfig.backgroundColor}">
+          {{loadingTime}}s
         </div>
-        <div class="widget-content p-0 gridster-item-content ml-0 mr-0 h-100">
-            <ng-template widgetHost class="h-100 p-0"></ng-template>
-        </div>
+        <button mat-button
+                mat-icon-button
+                [matMenuTriggerFor]="menu"
+                aria-label="More options"
+                matTooltip="More options"
+                *ngIf="!editMode"
+                [attr.data-cy]="'more-options-' + configuredWidget.baseAppearanceConfig.widgetTitle">
+          <mat-icon>more_vert</mat-icon>
+        </button>
+        <mat-menu #menu="matMenu">
+          <button mat-menu-item
+                  (click)="downloadDataAsFile()">
+            <mat-icon>get_app</mat-icon>
+            <span>Download data</span>
+          </button>
+          <button mat-menu-item
+                  (click)="startEditMode()"
+                  *ngIf="hasDataExplorerWritePrivileges"
+                  [attr.data-cy]="'start-edit-' + configuredWidget.baseAppearanceConfig.widgetTitle">
+            <mat-icon>edit</mat-icon>
+            <span>Edit Widget</span>
+          </button>
+        </mat-menu>
+        <button mat-button
+                mat-icon-button
+                *ngIf="editMode"
+                (click)="downloadDataAsFile()">
+          <mat-icon>get_app</mat-icon>
+        </button>
+        <button mat-button
+                mat-icon-button
+                [class.mat-raised-button]="currentlyConfiguredWidgetId === configuredWidget._id"
+                (click)="triggerWidgetEditMode()"
+                *ngIf="editMode"
+                [color]="currentlyConfiguredWidgetId === configuredWidget._id ? 'accent' : ''"
+                matTooltip="Edit widget"
+                [attr.data-cy]="'edit-' + configuredWidget.baseAppearanceConfig.widgetTitle">
+          <mat-icon>edit</mat-icon>
+        </button>
+        <button mat-button
+                mat-icon-button
+                (click)="removeWidget()"
+                matTooltip="Delete widget"
+                *ngIf="editMode && hasDataExplorerDeletePrivileges"
+                [attr.data-cy]="'remove-' + configuredWidget.baseAppearanceConfig.widgetTitle">
+          <mat-icon>clear</mat-icon>
+        </button>
+      </div>
     </div>
+    <div class="widget-content p-0 gridster-item-content ml-0 mr-0 h-100 mw-100">
+      <ng-template widgetHost class="h-100 p-0"></ng-template>
+      <div fxFlex="100"
+           fxLayout="column"
+           fxLayoutAlign="center center"
+           *ngIf="errorMessage">
+        <sp-exception-message [message]="errorMessage"
+                              [showDetails]="true"></sp-exception-message>
+      </div>
+    </div>
+  </div>
 </div>
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.scss b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.scss
index 7dfcbef..79be76d 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.scss
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.scss
@@ -46,6 +46,7 @@
     display: flex;
     flex-flow: column;
     height: 100%;
+    padding-top: 5px;
 }
 
 .box .row.content {
@@ -91,3 +92,12 @@
     text-align: center;
 }
 
+.h-0 {
+    height: 0px;
+}
+
+.mw-100 {
+    max-width: 100%;
+    width: 100%;
+    overflow-x: hidden;
+}
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
index 7163672..16dd074 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
@@ -21,22 +21,22 @@
   ComponentFactoryResolver,
   EventEmitter,
   Input,
+  OnDestroy,
   OnInit,
   Output,
   ViewChild
 } from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
 import { GridsterItemComponent } from 'angular-gridster2';
 import {
-  DateRange,
+  DashboardItem, DataExplorerDataConfig,
   DataExplorerWidgetModel,
   DataLakeMeasure,
   DataViewDataExplorerService,
-  DashboardItem,
+  DateRange,
   TimeSettings
 } from '@streampipes/platform-services';
-import { DataDownloadDialog } from '../datadownloadDialog/dataDownload.dialog';
-import { interval } from 'rxjs';
+import { DataDownloadDialogComponent } from '../../../core-ui/data-download-dialog/data-download-dialog.component';
+import { interval, Subscription } from 'rxjs';
 import { takeWhile } from 'rxjs/operators';
 import { DataExplorerWidgetRegistry } from '../../registry/data-explorer-widget-registry';
 import { WidgetDirective } from './widget.directive';
@@ -44,13 +44,15 @@
 import { WidgetTypeService } from '../../services/widget-type.service';
 import { AuthService } from '../../../services/auth.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
+import { DialogService, PanelType } from '@streampipes/shared-ui';
+import { StreamPipesErrorMessage } from '../../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
 
 @Component({
   selector: 'sp-data-explorer-dashboard-widget',
   templateUrl: './data-explorer-dashboard-widget.component.html',
   styleUrls: ['./data-explorer-dashboard-widget.component.scss']
 })
-export class DataExplorerDashboardWidgetComponent implements OnInit {
+export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
 
   @Input()
   dashboardItem: DashboardItem;
@@ -70,6 +72,12 @@
   @Input()
   currentlyConfiguredWidgetId: string;
 
+  @Input()
+  previewMode = false;
+
+  @Input()
+  gridMode = true;
+
   /**
    * This is the date range (start, end) to view the data and is set in data-explorer.ts
    */
@@ -92,23 +100,29 @@
   hasDataExplorerWritePrivileges = false;
   hasDataExplorerDeletePrivileges = false;
 
+  authSubscription: Subscription;
+  widgetTypeChangedSubscription: Subscription;
+  intervalSubscription: Subscription;
+
+  errorMessage: StreamPipesErrorMessage;
+
   @ViewChild(WidgetDirective, {static: true}) widgetHost!: WidgetDirective;
 
   constructor(private dataViewDataExplorerService: DataViewDataExplorerService,
-              private dialog: MatDialog,
+              private dialogService: DialogService,
               private componentFactoryResolver: ComponentFactoryResolver,
               private widgetTypeService: WidgetTypeService,
               private authService: AuthService) {
   }
 
   ngOnInit(): void {
-    this.authService.user$.subscribe(user => {
+    this.authSubscription = this.authService.user$.subscribe(user => {
       this.hasDataExplorerWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW);
       this.hasDataExplorerDeletePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_DELETE_DATA_EXPLORER_VIEW);
     });
     this.widgetLoaded = true;
     this.title = this.dataLakeMeasure.measureName;
-    this.widgetTypeService.widgetTypeChangeSubject.subscribe(typeChange => {
+    this.widgetTypeChangedSubscription = this.widgetTypeService.widgetTypeChangeSubject.subscribe(typeChange => {
       if (typeChange.widgetId === this.configuredWidget._id) {
         this.chooseWidget(typeChange.newWidgetTypeId);
       }
@@ -116,6 +130,15 @@
     this.chooseWidget(this.configuredWidget.widgetType);
   }
 
+  ngOnDestroy() {
+    if (this.authSubscription) {
+      this.authSubscription.unsubscribe();
+    }
+    if (this.widgetTypeChangedSubscription) {
+      this.widgetTypeChangedSubscription.unsubscribe();
+    }
+  }
+
   chooseWidget(widgetTypeId: string) {
     const widgets = DataExplorerWidgetRegistry.getAvailableWidgetTemplates();
     const widgetToDisplay = widgets.find(widget => widget.id === widgetTypeId);
@@ -136,12 +159,16 @@
     componentRef.instance.editMode = this.editMode;
     componentRef.instance.dataViewDashboardItem = this.dashboardItem;
     componentRef.instance.dataExplorerWidget = this.configuredWidget;
+    componentRef.instance.previewMode = this.previewMode;
+    componentRef.instance.gridMode = this.gridMode;
     const removeSub = componentRef.instance.removeWidgetCallback.subscribe(ev => this.removeWidget());
     const timerSub = componentRef.instance.timerCallback.subscribe(ev => this.handleTimer(ev));
+    const errorSub = componentRef.instance.errorCallback.subscribe(ev => this.errorMessage = ev);
 
     componentRef.onDestroy(destroy => {
       removeSub.unsubscribe();
       timerSub.unsubscribe();
+      errorSub.unsubscribe();
     });
   }
 
@@ -150,13 +177,14 @@
   }
 
   downloadDataAsFile() {
-    this.dialog.open(DataDownloadDialog, {
-      width: '600px',
+    this.dialogService.open(DataDownloadDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Download data',
+      width: '50vw',
       data: {
-        index: this.dataLakeMeasure.measureName,
-        date: DateRange.fromTimeSettings(this.timeSettings)
-      },
-      panelClass: 'custom-dialog-container'
+        'date': DateRange.fromTimeSettings(this.timeSettings),
+        'dataConfig': this.configuredWidget.dataConfig as DataExplorerDataConfig
+      }
     });
   }
 
@@ -174,7 +202,7 @@
 
   startLoadingTimer() {
     this.timerActive = true;
-    interval( 10 )
+    this.intervalSubscription = interval( 10 )
         .pipe(takeWhile(() => this.timerActive))
         .subscribe(value => {
       this.loadingTime = (value * 10 / 1000);
@@ -183,9 +211,11 @@
 
   stopLoadingTimer() {
     this.timerActive = false;
+    this.intervalSubscription.unsubscribe();
   }
 
   handleTimer(start: boolean) {
     start ? this.startLoadingTimer() : this.stopLoadingTimer();
   }
+
 }
diff --git a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
index a77a09d..151b503 100644
--- a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
+++ b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
@@ -20,20 +20,23 @@
 import { GridsterItem, GridsterItemComponent } from 'angular-gridster2';
 import { WidgetConfigurationService } from '../../../services/widget-configuration.service';
 import {
+  DashboardItem,
   DataExplorerDataConfig,
   DataExplorerField,
-  DataViewQueryGeneratorService,
   DataExplorerWidgetModel,
-  SpQueryResult,
-  DashboardItem,
   DatalakeRestService,
-  TimeSettings } from '@streampipes/platform-services';
+  DataViewQueryGeneratorService,
+  SpQueryResult,
+  StreamPipesErrorMessage,
+  TimeSettings
+} from '@streampipes/platform-services';
 import { ResizeService } from '../../../services/resize.service';
 import { FieldProvider } from '../../../models/dataview-dashboard.model';
-import { Observable, Subscription, zip } from 'rxjs';
+import { Observable, Subject, Subscription, zip } from 'rxjs';
 import { DataExplorerFieldProviderService } from '../../../services/data-explorer-field-provider-service';
 import { BaseWidgetData } from './data-explorer-widget-data';
 import { TimeSelectionService } from '../../../services/time-selection.service';
+import { catchError, switchMap } from 'rxjs/operators';
 
 @Directive()
 export abstract class BaseDataExplorerWidgetDirective<T extends DataExplorerWidgetModel> implements BaseWidgetData<T>, OnInit, OnDestroy {
@@ -46,12 +49,21 @@
   @Output()
   timerCallback: EventEmitter<boolean> = new EventEmitter();
 
+  @Output()
+  errorCallback: EventEmitter<StreamPipesErrorMessage> = new EventEmitter<StreamPipesErrorMessage>();
+
   @Input() gridsterItem: GridsterItem;
   @Input() gridsterItemComponent: GridsterItemComponent;
   @Input() editMode: boolean;
 
   @Input() timeSettings: TimeSettings;
 
+  @Input()
+  previewMode = false;
+
+  @Input()
+  gridMode = true;
+
   @Input() dataViewDashboardItem: DashboardItem;
   @Input() dataExplorerWidget: T;
 
@@ -71,6 +83,8 @@
   resizeSub: Subscription;
   timeSelectionSub: Subscription;
 
+  requestQueue$: Subject<Observable<SpQueryResult>[]> = new Subject<Observable<SpQueryResult>[]>();
+
   constructor(protected dataLakeRestService: DatalakeRestService,
               protected widgetConfigurationService: WidgetConfigurationService,
               protected resizeService: ResizeService,
@@ -80,9 +94,28 @@
   }
 
   ngOnInit(): void {
+    const heightOffset = this.gridMode ? 70 : 65;
+    const widthOffset = this.gridMode ? 10 : 10;
     this.showData = true;
     const sourceConfigs = this.dataExplorerWidget.dataConfig.sourceConfigs;
     this.fieldProvider = this.fieldService.generateFieldLists(sourceConfigs);
+
+    this.requestQueue$
+      .pipe(switchMap((observables) => {
+      this.errorCallback.emit(undefined);
+      return zip(...observables).pipe(catchError((err) => {
+        this.timerCallback.emit(false);
+        this.errorCallback.emit(err.error);
+        return [];
+      }));
+    }))
+      .subscribe(results => {
+      results.forEach((result, index) => result.sourceIndex = index);
+      this.validateReceivedData(results);
+      this.refreshView();
+      this.timerCallback.emit(false);
+    });
+
     this.widgetConfigurationSub = this.widgetConfigurationService.configurationChangedSubject.subscribe(refreshMessage => {
       if (refreshMessage.widgetId === this.dataExplorerWidget._id) {
         if (refreshMessage.refreshData) {
@@ -99,23 +132,28 @@
         }
       }
     });
-    this.resizeSub = this.resizeService.resizeSubject.subscribe(info => {
-      if (info.gridsterItem.id === this.dataExplorerWidget._id) {
-        this.onResize(this.gridsterItemComponent.width, this.gridsterItemComponent.height - 40);
-      }
-    });
+    if (!this.previewMode) {
+      this.resizeSub = this.resizeService.resizeSubject.subscribe(info => {
+        if (info.gridsterItem.id === this.dataExplorerWidget._id) {
+          this.onResize(this.gridsterItemComponent.width - widthOffset, this.gridsterItemComponent.height - heightOffset);
+        }
+      });
+    }
     this.timeSelectionSub = this.timeSelectionService.timeSelectionChangeSubject.subscribe(ts => {
       this.timeSettings = ts;
       this.updateData();
     });
     this.updateData();
-    this.onResize(this.gridsterItemComponent.width, this.gridsterItemComponent.height - 40);
+    this.onResize(this.gridsterItemComponent.width - widthOffset, this.gridsterItemComponent.height - heightOffset);
   }
 
   ngOnDestroy(): void {
     this.widgetConfigurationSub.unsubscribe();
-    this.resizeSub.unsubscribe();
+    if (this.resizeSub) {
+      this.resizeSub.unsubscribe();
+    }
     this.timeSelectionSub.unsubscribe();
+    this.requestQueue$.unsubscribe();
   }
 
   public removeWidget() {
@@ -140,35 +178,27 @@
   }
 
   private loadData(includeTooMuchEventsParameter: boolean) {
-
     let observables: Observable<SpQueryResult>[];
-
     if (includeTooMuchEventsParameter && !this.dataExplorerWidget.dataConfig.ignoreTooMuchDataWarning) {
       observables = this
-          .dataViewQueryGeneratorService
-          .generateObservables(
-              this.timeSettings.startTime,
-              this.timeSettings.endTime,
-              this.dataExplorerWidget.dataConfig as DataExplorerDataConfig,
-              BaseDataExplorerWidgetDirective.TOO_MUCH_DATA_PARAMETER
-          );
+        .dataViewQueryGeneratorService
+        .generateObservables(
+          this.timeSettings.startTime,
+          this.timeSettings.endTime,
+          this.dataExplorerWidget.dataConfig as DataExplorerDataConfig,
+          BaseDataExplorerWidgetDirective.TOO_MUCH_DATA_PARAMETER
+        );
     } else {
       observables = this
-          .dataViewQueryGeneratorService
-          .generateObservables(
-              this.timeSettings.startTime,
-              this.timeSettings.endTime,
-              this.dataExplorerWidget.dataConfig as DataExplorerDataConfig);
+        .dataViewQueryGeneratorService
+        .generateObservables(
+          this.timeSettings.startTime,
+          this.timeSettings.endTime,
+          this.dataExplorerWidget.dataConfig as DataExplorerDataConfig);
     }
 
     this.timerCallback.emit(true);
-    zip(...observables).subscribe(results => {
-      results.forEach((result, index) => result.sourceIndex = index);
-      this.validateReceivedData(results);
-      // this.onDataReceived(results);
-      this.refreshView();
-      this.timerCallback.emit(false);
-    });
+    this.requestQueue$.next(observables);
   }
 
   validateReceivedData(spQueryResults: SpQueryResult[]) {
diff --git a/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts b/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts
index b6927b1..1a75781 100644
--- a/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts
+++ b/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts
@@ -18,11 +18,16 @@
 
 import { EventEmitter } from '@angular/core';
 import { GridsterItem, GridsterItemComponent } from 'angular-gridster2';
-import { DataExplorerWidgetModel, DashboardItem, TimeSettings } from '@streampipes/platform-services';
+import {
+  DashboardItem,
+  DataExplorerWidgetModel,
+  StreamPipesErrorMessage,
+  TimeSettings } from '@streampipes/platform-services';
 
 export interface BaseWidgetData<T extends DataExplorerWidgetModel> {
   removeWidgetCallback: EventEmitter<boolean>;
   timerCallback: EventEmitter<boolean>;
+  errorCallback: EventEmitter<StreamPipesErrorMessage>;
 
   gridsterItem: GridsterItem;
   gridsterItemComponent: GridsterItemComponent;
@@ -32,4 +37,6 @@
 
   dataViewDashboardItem: DashboardItem;
   dataExplorerWidget: T;
+  previewMode: boolean;
+  gridMode: boolean;
 }
diff --git a/ui/src/app/data-explorer/components/widgets/correlation-chart/correlation-chart-widget.component.html b/ui/src/app/data-explorer/components/widgets/correlation-chart/correlation-chart-widget.component.html
index cd0e477..1f7c8ae 100644
--- a/ui/src/app/data-explorer/components/widgets/correlation-chart/correlation-chart-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/correlation-chart/correlation-chart-widget.component.html
@@ -19,14 +19,17 @@
 <div fxLayout="column" fxFlex="100"
      [ngStyle]="{background: dataExplorerWidget.baseAppearanceConfig.backgroundColor, color: dataExplorerWidget.baseAppearanceConfig.textColor}">
 
-    <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
-
-    <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
+    <sp-no-data-in-date-range
+        *ngIf="showNoDataInDateRange"
+        [viewDateRange]="timeSettings"
+        class="h-100">
+    </sp-no-data-in-date-range>
 
     <sp-too-much-data
             [amountOfEvents]="amountOfTooMuchEvents"
             (loadDataWithTooManyEventsEmitter)="loadDataWithTooManyEvents()"
-            *ngIf="showTooMuchData"></sp-too-much-data>
+            *ngIf="showTooMuchData" class="h-100">
+    </sp-too-much-data>
 
 
     <plotly-plot *ngIf="showData"
diff --git a/ui/src/app/data-explorer/components/widgets/correlation-chart/correlation-chart-widget.component.ts b/ui/src/app/data-explorer/components/widgets/correlation-chart/correlation-chart-widget.component.ts
index 7ee788b..3de451f 100644
--- a/ui/src/app/data-explorer/components/widgets/correlation-chart/correlation-chart-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/correlation-chart/correlation-chart-widget.component.ts
@@ -20,6 +20,7 @@
 import { BaseDataExplorerWidgetDirective } from '../base/base-data-explorer-widget.directive';
 import { CorrelationChartWidgetModel } from './model/correlation-chart-widget.model';
 import { DataExplorerField, SpQueryResult } from '@streampipes/platform-services';
+import { ColorUtils } from '../utils/color-utils';
 
 @Component({
   selector: 'sp-data-explorer-correlation-chart-widget',
@@ -37,12 +38,18 @@
   graph = {
     layout: {
       grid: {rows: this.rowNo, columns: this.fixedColNo, pattern: 'independent'},
+      margin: {
+        t: 35,
+        b: 35
+      },
       xaxis: {
+        automargin: true,
         title: {
           text: ''
         }
       },
       yaxis: {
+        automargin: true,
         title: {
           text: ''
         }
@@ -66,17 +73,6 @@
     this.updateAppearance();
   }
 
-  lightenColor(color: string, percent: number) {
-    const num = parseInt(color.replace('#', ''), 16);
-    const amt = Math.round(2.55 * percent);
-    const R = (num >> 16) + amt;
-    const B = (num >> 8 & 0x00FF) + amt;
-    const G = (num & 0x0000FF) + amt;
-    const result = '#' + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
-                  (B < 255 ? B < 1 ? 0 : B : 255) * 0x100 + (G < 255 ? G < 1 ? 0 : G : 255)).toString(16).slice(1);
-    return result;
-  }
-
   prepareData(result: SpQueryResult[]) {
 
     const xIndex = this.getColumnIndex(this.dataExplorerWidget.visualizationConfig.firstField, result[0]);
@@ -174,7 +170,7 @@
          colCount += 1;
        }
 
-       colorVal = this.lightenColor(colorVal, 11.);
+       colorVal = ColorUtils.lightenColor(colorVal, 11.);
 
     });
   }
diff --git a/ui/src/app/data-explorer/components/widgets/distribution-chart/config/distribution-chart-widget-config.component.html b/ui/src/app/data-explorer/components/widgets/distribution-chart/config/distribution-chart-widget-config.component.html
index b0d367d..2f51faa 100644
--- a/ui/src/app/data-explorer/components/widgets/distribution-chart/config/distribution-chart-widget-config.component.html
+++ b/ui/src/app/data-explorer/components/widgets/distribution-chart/config/distribution-chart-widget-config.component.html
@@ -31,7 +31,7 @@
   </mat-form-field>  
   
   <h5>Field</h5>
-    <sp-select-property [availableProperties]="fieldProvider.allFields"
+    <sp-select-property [availableProperties]="currentlyConfiguredWidget.visualizationConfig.displayType === 'heatmap' ? fieldProvider.numericFields : fieldProvider.allFields"
                         [selectedProperty]="currentlyConfiguredWidget.visualizationConfig.selectedProperty"
                         (changeSelectedProperty)="setSelectedProperty($event)">
     </sp-select-property>
diff --git a/ui/src/app/data-explorer/components/widgets/distribution-chart/config/distribution-chart-widget-config.component.ts b/ui/src/app/data-explorer/components/widgets/distribution-chart/config/distribution-chart-widget-config.component.ts
index 7e645c2..18f935a 100644
--- a/ui/src/app/data-explorer/components/widgets/distribution-chart/config/distribution-chart-widget-config.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/distribution-chart/config/distribution-chart-widget-config.component.ts
@@ -41,6 +41,9 @@
 
   updateDisplayType(selectedType: string) {
     this.currentlyConfiguredWidget.visualizationConfig.displayType = selectedType;
+    if (this.fieldProvider.numericFields.find(field => field === this.currentlyConfiguredWidget.visualizationConfig.selectedProperty) === undefined) {
+      this.currentlyConfiguredWidget.visualizationConfig.selectedProperty = this.fieldProvider.numericFields[0];
+    }
     this.triggerDataRefresh();
   }
 
diff --git a/ui/src/app/data-explorer/components/widgets/distribution-chart/distribution-chart-widget.component.html b/ui/src/app/data-explorer/components/widgets/distribution-chart/distribution-chart-widget.component.html
index ce9d36e..df75b8c 100644
--- a/ui/src/app/data-explorer/components/widgets/distribution-chart/distribution-chart-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/distribution-chart/distribution-chart-widget.component.html
@@ -19,14 +19,16 @@
 <div fxLayout="column" fxFlex="100"
      [ngStyle]="{background: dataExplorerWidget.baseAppearanceConfig.backgroundColor, color: dataExplorerWidget.baseAppearanceConfig.textColor}">
 
-    <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
-
-    <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
+    <sp-no-data-in-date-range
+        *ngIf="showNoDataInDateRange"
+        [viewDateRange]="timeSettings"
+        class="h-100">
+    </sp-no-data-in-date-range>
 
     <sp-too-much-data
             [amountOfEvents]="amountOfTooMuchEvents"
             (loadDataWithTooManyEventsEmitter)="loadDataWithTooManyEvents()"
-            *ngIf="showTooMuchData"></sp-too-much-data>
+            *ngIf="showTooMuchData" class="h-100"></sp-too-much-data>
 
     <plotly-plot *ngIf="showData && !(dataExplorerWidget.visualizationConfig.displayType === 'heatmap')"
                  [divId]="dataExplorerWidget._id"
diff --git a/ui/src/app/data-explorer/components/widgets/distribution-chart/value-heatmap/value-heatmap.component.ts b/ui/src/app/data-explorer/components/widgets/distribution-chart/value-heatmap/value-heatmap.component.ts
index 450f99d..5559ac2 100644
--- a/ui/src/app/data-explorer/components/widgets/distribution-chart/value-heatmap/value-heatmap.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/distribution-chart/value-heatmap/value-heatmap.component.ts
@@ -18,9 +18,9 @@
 
 import { Component, Input, OnInit } from '@angular/core';
 import { EChartsOption } from 'echarts';
-import { ECharts } from "echarts/core";
-import { DataExplorerWidgetModel, SpQueryResult } from "../../../../../../../dist/streampipes/platform-services";
-import { DistributionChartWidgetModel } from "../model/distribution-chart-widget.model";
+import { ECharts } from 'echarts/core';
+import { SpQueryResult } from '@streampipes/platform-services';
+import { DistributionChartWidgetModel } from '../model/distribution-chart-widget.model';
 
 @Component({
   selector: 'sp-data-explorer-value-heatmap-widget',
diff --git a/ui/src/app/data-explorer/components/widgets/heatmap/heatmap-widget.component.html b/ui/src/app/data-explorer/components/widgets/heatmap/heatmap-widget.component.html
index 24a404a..e953542 100644
--- a/ui/src/app/data-explorer/components/widgets/heatmap/heatmap-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/heatmap/heatmap-widget.component.html
@@ -18,14 +18,18 @@
 
   <div fxFlex="100" fxLayoutAlign="center center" fxLayout="column" class="main-panel">
 
-    <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
-
-    <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
+    <sp-no-data-in-date-range
+        *ngIf="showNoDataInDateRange"
+        [viewDateRange]="timeSettings"
+        class="h-100">
+    </sp-no-data-in-date-range>
 
     <sp-too-much-data
             [amountOfEvents]="amountOfTooMuchEvents"
             (loadDataWithTooManyEventsEmitter)="loadDataWithTooManyEvents()"
-            *ngIf="showTooMuchData"></sp-too-much-data>
+            *ngIf="showTooMuchData"
+            class="h-100">
+    </sp-too-much-data>
 
     <div class="value-panel">
       <div echarts [options]="option"
diff --git a/ui/src/app/data-explorer/components/widgets/image/config/image-widget-config.component.ts b/ui/src/app/data-explorer/components/widgets/image/config/image-widget-config.component.ts
index 19f55ef..ae971d4 100644
--- a/ui/src/app/data-explorer/components/widgets/image/config/image-widget-config.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/image/config/image-widget-config.component.ts
@@ -20,7 +20,7 @@
 import { BaseWidgetConfig } from '../../base/base-widget-config';
 import { ImageWidgetModel, ImageWidgetVisConfig } from '../model/image-widget.model';
 import { WidgetType } from '../../../../registry/data-explorer-widgets';
-import { DataExplorerField } from "../../../../../../../dist/streampipes/platform-services";
+import { DataExplorerField } from '@streampipes/platform-services';
 
 @Component({
   selector: 'sp-data-explorer-image-widget-config',
diff --git a/ui/src/app/data-explorer/components/widgets/image/image-widget.component.html b/ui/src/app/data-explorer/components/widgets/image/image-widget.component.html
index 1577277..a2bd9ec 100644
--- a/ui/src/app/data-explorer/components/widgets/image/image-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/image/image-widget.component.html
@@ -19,8 +19,6 @@
 
 <div fxFlex="100" fxLayoutAlign="center center" fxLayout="column" class="main-panel">
 
-    <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
-
     <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
 
 
diff --git a/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.html b/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.html
index 074d1fa..1dbe8da 100644
--- a/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.html
@@ -19,14 +19,16 @@
 <div fxLayout="column" fxFlex="100"
      [ngStyle]="{background: dataExplorerWidget.baseAppearanceConfig.backgroundColor, color: dataExplorerWidget.baseAppearanceConfig.textColor}">
 
-    <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
-
-    <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
+    <sp-no-data-in-date-range
+        *ngIf="showNoDataInDateRange"
+        [viewDateRange]="timeSettings"
+        class="h-100">
+    </sp-no-data-in-date-range>
 
     <sp-too-much-data
             [amountOfEvents]="amountOfTooMuchEvents"
             (loadDataWithTooManyEventsEmitter)="loadDataWithTooManyEvents()"
-            *ngIf="showTooMuchData"></sp-too-much-data>
+            *ngIf="showTooMuchData" class="h-100"></sp-too-much-data>
 
     <plotly-plot *ngIf="showData"
                  [divId]="dataExplorerWidget._id"
diff --git a/ui/src/app/data-explorer/components/widgets/map/map-widget.component.html b/ui/src/app/data-explorer/components/widgets/map/map-widget.component.html
index fdacf07..38fd24a 100644
--- a/ui/src/app/data-explorer/components/widgets/map/map-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/map/map-widget.component.html
@@ -18,14 +18,15 @@
 
 <div fxFlex="100" fxLayoutAlign="center center" fxLayout="column" class="main-panel">
 
-    <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
-
-    <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
+    <sp-no-data-in-date-range
+        *ngIf="showNoDataInDateRange"
+        [viewDateRange]="timeSettings" class="h-100">
+    </sp-no-data-in-date-range>
 
     <sp-too-much-data
             [amountOfEvents]="amountOfTooMuchEvents"
             (loadDataWithTooManyEventsEmitter)="loadDataWithTooManyEvents()"
-            *ngIf="showTooMuchData"></sp-too-much-data>
+            *ngIf="showTooMuchData" class="h-100"></sp-too-much-data>
 
     <div *ngIf="showData">
         <div [ngStyle]="{'width': mapWidth + 'px', 'height': mapHeight + 'px'}"
diff --git a/ui/src/app/data-explorer/components/widgets/table/table-widget.component.html b/ui/src/app/data-explorer/components/widgets/table/table-widget.component.html
index 5102e53..a1b2a9e 100644
--- a/ui/src/app/data-explorer/components/widgets/table/table-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/table/table-widget.component.html
@@ -19,15 +19,18 @@
 <div fxLayout="column" fxFlex="100"
      [ngStyle]="{background: dataExplorerWidget.baseAppearanceConfig.backgroundColor, color: dataExplorerWidget.baseAppearanceConfig.textColor}">
 
-    <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
-
-    <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
+    <sp-no-data-in-date-range
+        *ngIf="showNoDataInDateRange"
+        [viewDateRange]="timeSettings"
+        class="h-100">
+    </sp-no-data-in-date-range>
 
     <sp-too-much-data
             [amountOfEvents]="amountOfTooMuchEvents"
             (loadDataWithTooManyEventsEmitter)="loadDataWithTooManyEvents()"
             *ngIf="showTooMuchData"
-            ></sp-too-much-data>
+            class="h-100">
+    </sp-too-much-data>
 
     <div class="table-container">
         <table
diff --git a/ui/src/app/data-explorer/components/widgets/time-series-chart/config/time-series-chart-widget-config.component.ts b/ui/src/app/data-explorer/components/widgets/time-series-chart/config/time-series-chart-widget-config.component.ts
index 73e7e2d..f359700 100644
--- a/ui/src/app/data-explorer/components/widgets/time-series-chart/config/time-series-chart-widget-config.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/time-series-chart/config/time-series-chart-widget-config.component.ts
@@ -37,14 +37,56 @@
     super(widgetConfigurationService, fieldService);
   }
 
-  presetColors: string[] = ['#39B54A', '#1B1464', '#f44336', '#4CAF50', '#FFEB3B', '#FFFFFF', '#000000'];
-
+  presetColors: string[] = [
+                          '#39B54A', 
+                          '#1B1464', 
+                          '#f44336', 
+                          '#FFEB3B', 
+                          '#000000', 
+                          '#433BFF', 
+                          '#FF00E4', 
+                          '#FD8B00', 
+                          '#FD8B00',
+                          '#00FFD5',
+                          '#581845',
+                          '#767676',
+                          '#4300BF',
+                          '#6699D4',
+                          '#D466A1'
+                        ];
+                        
   ngOnInit(): void {
     super.onInit();
   }
 
   setSelectedProperties(selectedColumns: DataExplorerField[]) {
     this.currentlyConfiguredWidget.visualizationConfig.selectedTimeSeriesChartProperties = selectedColumns;
+
+    const numericPlusBooleanFields = this.fieldProvider.numericFields.concat(this.fieldProvider.booleanFields);
+
+    const currentColors =  this.currentlyConfiguredWidget.visualizationConfig.chosenColor;
+    const currentNames =  this.currentlyConfiguredWidget.visualizationConfig.displayName;
+    const currentTypes =  this.currentlyConfiguredWidget.visualizationConfig.displayType;
+    const currentAxis =  this.currentlyConfiguredWidget.visualizationConfig.chosenAxis;
+
+    const lenBefore = Object.keys(currentAxis).length
+
+    numericPlusBooleanFields.map((field, index) => {
+      const name = field.fullDbName + field.sourceIndex
+      if (!(name in currentColors)) {
+        console.log("choosing color " + lenBefore+index + "   " + this.presetColors[lenBefore+index]);
+        currentColors[name] = this.presetColors[lenBefore+index];
+        currentNames[name] = field.fullDbName;
+        currentTypes[name] = 'lines';
+        currentAxis[name] = 'left';
+      }
+    });
+
+    this.currentlyConfiguredWidget.visualizationConfig.chosenColor = currentColors;
+    this.currentlyConfiguredWidget.visualizationConfig.displayName = currentNames;
+    this.currentlyConfiguredWidget.visualizationConfig.displayType = currentTypes;
+    this.currentlyConfiguredWidget.visualizationConfig.chosenAxis = currentAxis
+
     // this.currentlyConfiguredWidget.dataConfig.yKeys = this.getRuntimeNames(selectedColumns);
     this.triggerDataRefresh();
   }
@@ -82,6 +124,7 @@
     const axes = {};
 
     numericPlusBooleanFields.map((field, index) => {
+      console.log("field full db name " + field.fullDbName)
       colors[field.fullDbName + field.sourceIndex] = this.presetColors[index];
       names[field.fullDbName + field.sourceIndex] = field.fullDbName;
       dTypes[field.fullDbName  + field.sourceIndex] = 'lines';
diff --git a/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.html b/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.html
index 7a5a7e9..ac729ca 100644
--- a/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.html
@@ -18,14 +18,17 @@
 
 <div fxLayout="column" fxFlex="100" [ngStyle]="{background: dataExplorerWidget.baseAppearanceConfig.backgroundColor, color: dataExplorerWidget.baseAppearanceConfig.textColor}">
 
-        <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
-
-        <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
+        <sp-no-data-in-date-range
+            *ngIf="showNoDataInDateRange"
+            [viewDateRange]="timeSettings"
+            class="h-100">
+        </sp-no-data-in-date-range>
 
         <sp-too-much-data
                 [amountOfEvents]="amountOfTooMuchEvents"
                 (loadDataWithTooManyEventsEmitter)="loadDataWithTooManyEvents()"
-                *ngIf="showTooMuchData"></sp-too-much-data>
+                *ngIf="showTooMuchData" class="h-100">
+        </sp-too-much-data>
 
         <plotly-plot *ngIf="showData"
                      [divId]="dataExplorerWidget._id"
diff --git a/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.ts b/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.ts
index 9e851b4..b1f76f2 100644
--- a/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.ts
@@ -20,6 +20,7 @@
 import { BaseDataExplorerWidgetDirective } from '../base/base-data-explorer-widget.directive';
 import { TimeSeriesChartWidgetModel } from './model/time-series-chart-widget.model';
 import { DataExplorerField, SpQueryResult } from '@streampipes/platform-services';
+import { ColorUtils } from '../utils/color-utils';
 
 @Component({
   selector: 'sp-data-explorer-time-series-chart-widget',
@@ -28,7 +29,23 @@
 })
 export class TimeSeriesChartWidgetComponent extends BaseDataExplorerWidgetDirective<TimeSeriesChartWidgetModel> implements OnInit {
 
-  presetColors: string[] = ['#39B54A', '#1B1464', '#f44336', '#4CAF50', '#FFEB3B', '#FFFFFF', '#000000'];
+  presetColors: string[] = [
+    '#39B54A',
+    '#1B1464',
+    '#f44336',
+    '#FFEB3B',
+    '#000000',
+    '#433BFF',
+    '#FF00E4',
+    '#FD8B00',
+    '#FD8B00',
+    '#00FFD5',
+    '#581845',
+    '#767676',
+    '#4300BF',
+    '#6699D4',
+    '#D466A1'
+  ];
 
   groupKeeper: {} = {};
 
@@ -59,11 +76,19 @@
       plot_bgcolor: '#fff',
       paper_bgcolor: '#fff',
       yaxis: {
-        fixedrange: true
+        fixedrange: true,
+        automargin: true
+      },
+      margin: {
+        t: 35,
+        b: 35
       },
       updatemenus: this.updatemenus,
 
       hovermode: 'x',
+      hoverlabel: {
+        namelength: 200
+      },
       showlegend: true,
       shapes: [],
       selectdirection: 'h',
@@ -96,28 +121,20 @@
         }
       ],
       direction: 'left',
-      pad: { 'r': 10, 't': 10 },
+      pad: {'r': 10, 't': 10},
       showactive: true,
       type: 'buttons',
       x: 0.0,
       xanchor: 'left',
       y: 1.3,
       yanchor: 'top',
-      font: { color: this.dataExplorerWidget.baseAppearanceConfig.textColor },
-      bgcolor: this.dataExplorerWidget.baseAppearanceConfig.backgroundColor,
+      font: {color: this.dataExplorerWidget.baseAppearanceConfig.textColor},
+      plot_bgcolor: this.dataExplorerWidget.baseAppearanceConfig.backgroundColor,
+      paper_bgcolor: this.dataExplorerWidget.baseAppearanceConfig.backgroundColor,
       bordercolor: '#000'
     }];
 
     super.ngOnInit();
-    this.resizeService.resizeSubject.subscribe(info => {
-      if (info.gridsterItem.id === this.gridsterItem.id) {
-        setTimeout(() => {
-          this.graph.layout.autosize = false;
-          (this.graph.layout as any).width = (info.gridsterItemComponent.width - this.offsetRightLineChart);
-          (this.graph.layout as any).height = (info.gridsterItemComponent.height - 80);
-        }, 100);
-      }
-    });
   }
 
   transformData(data: SpQueryResult,
@@ -157,7 +174,7 @@
               Object.entries(group['tags']).forEach(
                 ([key, val]) => {
                   if (name in this.groupKeeper) {
-                    if (this.groupKeeper[name].indexOf(val) === - 1) {
+                    if (this.groupKeeper[name].indexOf(val) === -1) {
                       this.groupKeeper[name].push(val);
                     }
                   } else {
@@ -196,20 +213,6 @@
     return Object.values(tmpLineChartTraces);
   }
 
-  lightenColor(color: string, percent: number) {
-    const num = parseInt(color.replace('#', ''), 16);
-    const amt = Math.round(2.55 * percent);
-    // tslint:disable-next-line:no-bitwise
-    const R = (num >> 16) + amt;
-    // tslint:disable-next-line:no-bitwise
-    const B = (num >> 8 & 0x00FF) + amt;
-    // tslint:disable-next-line:no-bitwise
-    const G = (num & 0x0000FF) + amt;
-    const result = '#' + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
-                  (B < 255 ? B < 1 ? 0 : B : 255) * 0x100 + (G < 255 ? G < 1 ? 0 : G : 255)).toString(16).slice(1);
-    return result;
-  }
-
   setStartX(startX: string) {
     this.selectedStartX = startX;
   }
@@ -234,12 +237,14 @@
         spikedash: 'dash',
         spikecolor: '#666666',
         spikethickness: 2,
+        automargin: true,
       };
       this.graph.layout.hovermode = 'x';
 
     } else {
       this.graph.layout['xaxis'] = {
         type: 'date',
+        automargin: true,
       };
       this.graph.layout.hovermode = '';
     }
@@ -276,7 +281,7 @@
           index = pastGroups;
 
           if (this.data[index] !== undefined) {
-            this.data[index]['marker'] = { 'color': '' };
+            this.data[index]['marker'] = {'color': ''};
 
             if (!(name in this.dataExplorerWidget.visualizationConfig.chosenColor)) {
               this.dataExplorerWidget.visualizationConfig.chosenColor[name] = this.presetColors[index];
@@ -302,7 +307,7 @@
             if (setType === 'bar') {
               visualizationOptions = barVisualizationOptions;
             }
-            if (setType === 'lines' || setType === 'lines+markers')  {
+            if (setType === 'lines' || setType === 'lines+markers') {
               visualizationOptions = lineVisualizationOptions;
             }
             if (setType === 'symbol_markers') {
@@ -320,7 +325,7 @@
               if (visualizationTypePosition === (visualizationOptions.length - 1)) {
                 dashType = visualizationOptions[0];
                 dashTypeKeeper[name] = dashType;
-                color = this.lightenColor(colorKeeper[name], 11.0);
+                color = ColorUtils.lightenColor(colorKeeper[name], 11.0);
                 colorKeeper[name] = color;
               } else {
                 dashType = visualizationOptions[visualizationTypePosition + 1];
@@ -344,16 +349,16 @@
 
             if (setType === 'bar') {
               this.data[index].marker['pattern'] = {
-                  'shape' : dashType,
-                  'fillmode' : 'overlay',
-                  'fgcolor' : '#ffffff',
-                  // 'size' : 3,
+                'shape': dashType,
+                'fillmode': 'overlay',
+                'fgcolor': '#ffffff',
+                // 'size' : 3,
               };
             } else {
               if (setType === 'lines' || setType === 'lines+markers') {
                 this.data[index]['line'] = {
-                              'dash' : dashType,
-                              'width' : 3,
+                  'dash': dashType,
+                  'width': 3,
                 };
               }
             }
@@ -391,10 +396,10 @@
 
             if (setAxis === 'y2') {
               this.graph.layout['yaxis2'] = {
-                                              title: '',
-                                              overlaying: 'y',
-                                              side: 'right'
-                                            };
+                title: '',
+                overlaying: 'y',
+                side: 'right'
+              };
             }
 
             pastGroups += 1;
@@ -409,9 +414,11 @@
   }
 
   onResize(width: number, height: number) {
-    this.graph.layout.autosize = false;
-    (this.graph.layout as any).width = width;
-    (this.graph.layout as any).height = height;
+    setTimeout(() => {
+      this.graph.layout.autosize = false;
+      (this.graph.layout as any).width = width - this.offsetRightLineChart;
+      (this.graph.layout as any).height = height;
+    }, 10);
   }
 
   beforeDataFetched() {
@@ -422,19 +429,19 @@
   onDataReceived(spQueryResults: SpQueryResult[]) {
     this.data = [];
 
-      // this.setShownComponents(true, false, false, false);
-      this.groupKeeper = {};
+    // this.setShownComponents(true, false, false, false);
+    this.groupKeeper = {};
 
-      this.orderedSelectedProperties = [];
+    this.orderedSelectedProperties = [];
 
-      spQueryResults.map((spQueryResult, index) => {
-        const res = this.transformData(spQueryResult, spQueryResult.sourceIndex);
-        res.forEach(item => {
-          this.data = this.data.concat(item);
-        });
+    spQueryResults.map((spQueryResult, index) => {
+      const res = this.transformData(spQueryResult, spQueryResult.sourceIndex);
+      res.forEach(item => {
+        this.data = this.data.concat(item);
       });
+    });
 
-      this.setShownComponents(false, true, false, false);
+    this.setShownComponents(false, true, false, false);
 
   }
 
diff --git a/ui/src/app/data-explorer/components/widgets/utils/aggregate-configuration/aggregate-configuration.component.ts b/ui/src/app/data-explorer/components/widgets/utils/aggregate-configuration/aggregate-configuration.component.ts
index 918eec6..43fdf8c 100644
--- a/ui/src/app/data-explorer/components/widgets/utils/aggregate-configuration/aggregate-configuration.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/utils/aggregate-configuration/aggregate-configuration.component.ts
@@ -36,9 +36,7 @@
     {value: 'm', label: 'Minute'},
     {value: 'h', label: 'Hour'},
     {value: 'd', label: 'Day'},
-    {value: 'w', label: 'Week'},
-    {value: 'month', label: 'Month'},
-    {value: 'year', label: 'Year'}
+    {value: 'w', label: 'Week'}
   ];
 
   constructor(private widgetConfigService: WidgetConfigurationService) {
diff --git a/ui/src/app/data-explorer/components/widgets/utils/color-utils.ts b/ui/src/app/data-explorer/components/widgets/utils/color-utils.ts
new file mode 100644
index 0000000..30d39de
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/utils/color-utils.ts
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+export class ColorUtils {
+
+  static lightenColor(color: string,
+                      percent: number): string {
+    const num = parseInt(color.replace('#', ''), 16);
+    const amt = Math.round(2.55 * percent);
+    // tslint:disable-next-line:no-bitwise
+    const R = (num >> 16) + amt;
+    // tslint:disable-next-line:no-bitwise
+    const B = (num >> 8 & 0x00FF) + amt;
+    // tslint:disable-next-line:no-bitwise
+    const G = (num & 0x0000FF) + amt;
+    const result = '#' + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
+      (B < 255 ? B < 1 ? 0 : B : 255) * 0x100 + (G < 255 ? G < 1 ? 0 : G : 255)).toString(16).slice(1);
+    return result;
+  }
+}
diff --git a/ui/src/app/data-explorer/components/widgets/utils/no-data/no-data-in-date-range.component.html b/ui/src/app/data-explorer/components/widgets/utils/no-data/no-data-in-date-range.component.html
index c409e7e..6e31fd5 100644
--- a/ui/src/app/data-explorer/components/widgets/utils/no-data/no-data-in-date-range.component.html
+++ b/ui/src/app/data-explorer/components/widgets/utils/no-data/no-data-in-date-range.component.html
@@ -16,12 +16,12 @@
   ~
   -->
 
-<div fxLayout="column" fxLayoutAlign="space-around center" >
+<div fxLayout="column" fxLayoutAlign="center center" fxFlex="100">
 
-    <div  fxLayout="row" fxLayoutAlign="center center" style="margin-top: 30px">
+    <div  fxLayout="row" fxLayoutAlign="center center">
         <!-- TODO Icon -->
     </div>
-    <div fxLayout="column" fxLayoutAlign="center center" style="margin-top: 30px">
+    <div fxLayout="column" fxLayoutAlign="center center" style="margin-top: 10px">
         <div class="default-text">Found no data in selected time range</div>
         <div class="default-text date-range-text">{{viewDateRange.startTime | date:'MM/dd/yyyy HH:mm'}} - {{viewDateRange.endTime | date:'MM/dd/yyyy HH:mm'}}</div>
 
diff --git a/ui/src/app/data-explorer/components/widgets/utils/select-color-properties/select-color-properties.component.html b/ui/src/app/data-explorer/components/widgets/utils/select-color-properties/select-color-properties.component.html
index d7f91c9..44b78a9 100644
--- a/ui/src/app/data-explorer/components/widgets/utils/select-color-properties/select-color-properties.component.html
+++ b/ui/src/app/data-explorer/components/widgets/utils/select-color-properties/select-color-properties.component.html
@@ -38,7 +38,7 @@
                       [checked]="isSelected(field)" 
                       (change)="toggleFieldSelection(field)">
             <b>{{field.runtimeName}}</b>
-            {{'(' + (field.aggregation ? field.aggregation + ', ' : '') + field.measure + ')'}}
+            {{'(' + (field.aggregation ? field.aggregation + ', ' : '') + field.measure + ' #' + (field.sourceIndex + 1).toString() + ')'}}
         </mat-checkbox>
         <div fxFlex 
              fxLayoutAlign="end center" 
diff --git a/ui/src/app/data-explorer/components/widgets/utils/select-property/select-property.component.html b/ui/src/app/data-explorer/components/widgets/utils/select-property/select-property.component.html
index 05695f9..0d372b6 100644
--- a/ui/src/app/data-explorer/components/widgets/utils/select-property/select-property.component.html
+++ b/ui/src/app/data-explorer/components/widgets/utils/select-property/select-property.component.html
@@ -21,7 +21,7 @@
     <mat-select [ngModel]="selectedProperty" (selectionChange)="triggerSelectedProperty($event.value)" [compareWith]="compare">
         <mat-option *ngFor="let column of availableProperties" [value]="column" style="background-color: #FFFFFF">
             <b>{{column.runtimeName}}</b>
-            {{'(' +(column.aggregation ? column.aggregation + ', ': '') + column.measure +')'}}
+            {{'(' +(column.aggregation ? column.aggregation + ', ': '') + column.measure + ' #' + (column.sourceIndex + 1).toString() + ')'}}
         </mat-option>
     </mat-select>
 </mat-form-field>
diff --git a/ui/src/app/data-explorer/components/widgets/utils/too-much-data/too-much-data.component.html b/ui/src/app/data-explorer/components/widgets/utils/too-much-data/too-much-data.component.html
index 9a9a43a..a30ba99 100644
--- a/ui/src/app/data-explorer/components/widgets/utils/too-much-data/too-much-data.component.html
+++ b/ui/src/app/data-explorer/components/widgets/utils/too-much-data/too-much-data.component.html
@@ -15,13 +15,13 @@
   ~ limitations under the License.
   ~
   -->
-<div fxLayout="column" fxLayoutAlign="space-around center" >
+<div fxLayout="column" fxLayoutAlign="center center" fxFlex="100">
 
-    <div  fxLayout="row" fxLayoutAlign="center center" style="margin-top: 30px">
+    <div  fxLayout="row" fxLayoutAlign="center center">
         <i class="material-icons" style="margin-top: 8px">warning</i>
-        <h2>Warning</h2>
+        <h2>&nbsp;Warning</h2>
     </div>
-    <div fxLayout="column" fxLayoutAlign="center center" style="margin-top: 30px">
+    <div fxLayout="column" fxLayoutAlign="center center" style="margin-top: 10px">
         <div class="default-text">This widget tries to load too much data (#Events: {{amountOfEvents}})</div>
         <div class="default-text date-range-text">Please change the widget settings or decrease the time range</div>
 
diff --git a/ui/src/app/data-explorer/data-explorer-panel.can-deactivate.guard.ts b/ui/src/app/data-explorer/data-explorer-panel.can-deactivate.guard.ts
new file mode 100644
index 0000000..d998b07
--- /dev/null
+++ b/ui/src/app/data-explorer/data-explorer-panel.can-deactivate.guard.ts
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { DataExplorerDashboardPanelComponent } from './components/panel/data-explorer-dashboard-panel.component';
+import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot } from '@angular/router';
+import { Observable } from 'rxjs';
+
+@Injectable({providedIn: 'root'})
+export class DataExplorerPanelCanDeactivateGuard implements CanDeactivate<DataExplorerDashboardPanelComponent> {
+
+  canDeactivate(
+    component: DataExplorerDashboardPanelComponent,
+    route: ActivatedRouteSnapshot,
+    state: RouterStateSnapshot
+  ): Observable<boolean> | boolean {
+
+    return component.confirmLeaveDashboard(route, state);
+  }
+}
diff --git a/ui/src/app/data-explorer/data-explorer.component.css b/ui/src/app/data-explorer/data-explorer.component.css
deleted file mode 100644
index 4482be5..0000000
--- a/ui/src/app/data-explorer/data-explorer.component.css
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-.mr-20 {
-    margin-right:20px;
-}
-
-.dashboard-panel {
-    height: 100%;
-    flex-direction: column;
-    box-sizing: border-box;
-    display: flex;
-    flex: 1 1 100%;
-    overflow-y: auto;
-}
-
-.ribbon {
-    position: absolute;
-    right: 5px; top: 55px;
-    z-index: 1;
-    overflow: hidden;
-    width: 75px; height: 75px;
-    text-align: right;
-}
-.ribbon span {
-    font-weight: bold;
-    color: #FFF;
-    text-transform: uppercase;
-    text-align: center;
-    line-height: 20px;
-    transform: rotate(45deg);
-    -webkit-transform: rotate(45deg);
-    width: 100px;
-    display: block;
-    background: #f5b53f;
-    background: linear-gradient(#f5b53f 0%, #f5b53f 100%);
-    position: absolute;
-    top: 19px; right: -21px;
-}
-.ribbon span::before {
-    content: "";
-    position: absolute; left: 0px; top: 100%;
-    z-index: -1;
-    border-left: 3px solid #f5b53f;
-    border-right: 3px solid transparent;
-    border-bottom: 3px solid transparent;
-    border-top: 3px solid #f5b53f;
-}
-
-.ribbon span::after {
-    content: "";
-    position: absolute; right: 0px; top: 100%;
-    z-index: -1;
-    border-left: 3px solid transparent;
-    border-right: 3px solid #f5b53f;
-    border-bottom: 3px solid transparent;
-    border-top: 3px solid #f5b53f;
-}
-
-.fixed-height {
-    height: 50px;
-}
-
-.data-explorer-options {
-    padding:0px;
-}
-
-.data-explorer-options-item {
-    display: inline;
-    margin-right: 10px;
-}
-
-.pl-10 {
-    padding-left: 10px;
-}
diff --git a/ui/src/app/data-explorer/data-explorer.component.html b/ui/src/app/data-explorer/data-explorer.component.html
deleted file mode 100644
index b4f8b0f..0000000
--- a/ui/src/app/data-explorer/data-explorer.component.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div fxLayout="column" class="page-container">
-    <div fxLayout="row" class="p-0 sp-bg-lightgray">
-        <div fxFlex="100" class="page-container-nav">
-            <div fxFlex="100" fxLayout="row">
-                <div fxFlex fxLayoutAlign="start center">
-                    <mat-tab-group [selectedIndex]="selectedIndex"
-                                   (selectedIndexChange)="selectDashboardInTab($event)"
-                                   color="accent">
-                        <mat-tab data-cy="data-explorer-start-tab"
-                                 label="Start"></mat-tab>
-                        <mat-tab *ngFor="let dataViewDashboard of dataViewDashboards"
-                                 label="{{dataViewDashboard.name}}"></mat-tab>
-                    </mat-tab-group>
-                </div>
-
-                <div fxFlex fxLayoutAlign="end center" *ngIf="selectedIndex > 0">
-                    <button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Options" data-cy="options-data-explorer">
-                        <mat-icon>more_vert</mat-icon>
-                    </button>
-                    <mat-menu #menu="matMenu">
-                        <button mat-menu-item (click)="triggerEditMode()"
-                                *ngIf="!editMode && hasDataExplorerWritePrivileges"
-                                data-cy="options-edit-dashboard">
-                            <mat-icon>edit</mat-icon>
-                            <span>Edit dashboard</span>
-                        </button>
-                        <button mat-menu-item (click)="getDashboards(selectedDataViewDashboard._id)">
-                            <mat-icon>refresh</mat-icon>
-                            <span>Reload dashboard</span>
-                        </button>
-                        <button mat-menu-item (click)="timeRangeVisible = true" *ngIf="!editMode && !timeRangeVisible">
-                            <mat-icon>alarm_on</mat-icon>
-                            <span>Show time range selector</span>
-                        </button>
-                        <button mat-menu-item (click)="timeRangeVisible = false" *ngIf="!editMode && timeRangeVisible">
-                            <mat-icon>alarm_off</mat-icon>
-                            <span>Hide time range selector</span>
-                        </button>
-                        <button mat-menu-item *ngIf="hasDataExplorerDeletePrivileges" (click)="deleteDashboard(selectedDataViewDashboard)">
-                            <mat-icon>clear</mat-icon>
-                            <span>Delete dashboard</span>
-                        </button>
-                    </mat-menu>
-                </div>
-            </div>
-        </div>
-    </div>
-
-
-    <div fxLayout="column" fxFlex="100" *ngIf="dashboardsLoaded">
-        <sp-data-explorer-dashboard-overview (selectDashboardEmitter)="openDashboard($event)"
-                                             (reloadDashboardsEmitter)="getDashboards()"
-                                             [dataViewDashboards]="dataViewDashboards"
-                                             *ngIf="!dashboardTabSelected">
-
-        </sp-data-explorer-dashboard-overview>
-        <sp-data-explorer-dashboard-panel fxLayout="column"
-                                          #dashboardPanel
-                                          (resetDashboardChanges)="resetDashboardChanges()"
-                                          [(editMode)]="editMode"
-                                          [dashboard]="selectedDataViewDashboard"
-                                          [timeSettings]="selectedDataViewDashboard.dashboardTimeSettings"
-                                          [timeRangeVisible]="timeRangeVisible"
-                                          class="dashboard-panel"
-                                          *ngIf="dashboardTabSelected">
-        </sp-data-explorer-dashboard-panel>
-    </div>
-</div>
diff --git a/ui/src/app/data-explorer/data-explorer.component.ts b/ui/src/app/data-explorer/data-explorer.component.ts
deleted file mode 100644
index 214e3db..0000000
--- a/ui/src/app/data-explorer/data-explorer.component.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { DataViewDataExplorerService, Dashboard } from '@streampipes/platform-services';
-import { RefreshDashboardService } from './services/refresh-dashboard.service';
-import { DataExplorerDashboardPanelComponent } from './components/panel/data-explorer-dashboard-panel.component';
-import { Tuple2 } from '../core-model/base/Tuple2';
-import { ActivatedRoute } from '@angular/router';
-import { AuthService } from '../services/auth.service';
-import { UserPrivilege } from '../_enums/user-privilege.enum';
-
-@Component({
-  selector: 'sp-data-explorer',
-  templateUrl: './data-explorer.component.html',
-  styleUrls: ['./data-explorer.component.css']
-})
-export class DataExplorerComponent implements OnInit {
-
-  selectedDataViewDashboard: Dashboard;
-  selectedIndex = 0;
-  dashboardsLoaded = false;
-  dashboardTabSelected = false;
-
-  timeRangeVisible = true;
-
-  editMode = true;
-  dataViewDashboards: Dashboard[];
-
-  routeParams: any;
-
-  hasDataExplorerWritePrivileges = false;
-  hasDataExplorerDeletePrivileges = false;
-
-  @ViewChild('dashboardPanel') dashboardPanel: DataExplorerDashboardPanelComponent;
-
-  constructor(private dataViewService: DataViewDataExplorerService,
-              private refreshDashboardService: RefreshDashboardService,
-              private route: ActivatedRoute,
-              private authService: AuthService,
-              private dashboardService: DataViewDataExplorerService) {
-  }
-
-
-  public ngOnInit() {
-    this.authService.user$.subscribe(user => {
-      this.hasDataExplorerWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW);
-      this.hasDataExplorerDeletePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_DELETE_DATA_EXPLORER_VIEW);
-    });
-    this.route.queryParams.subscribe(params => {
-      this.routeParams = { startTime: params['startTime'], endTime: params['endTime'], dashboardId: params['dashboardId'] };
-      this.getDashboards();
-    });
-    this.refreshDashboardService.refreshSubject.subscribe(currentDashboardId => {
-      this.getDashboards(currentDashboardId);
-    });
-
-  }
-
-  openDashboard(dashboard: Tuple2<Dashboard, boolean>) {
-    const index = this.dataViewDashboards.indexOf(dashboard.a);
-    this.selectDashboard((index + 1), dashboard.b);
-  }
-
-  selectDashboardInTab(index: number) {
-    if (index !== this.selectedIndex) {
-      this.selectDashboard(index);
-    }
-  }
-
-  selectDashboard(index: number, editMode = false) {
-    this.selectedIndex = index;
-    this.editMode = editMode;
-    if (index === 0) {
-      this.dashboardTabSelected = false;
-    } else {
-      this.dashboardTabSelected = true;
-      this.applyTimeSettings(this.dataViewDashboards[(index - 1)]);
-      this.selectedDataViewDashboard = this.dataViewDashboards[(index - 1)];
-    }
-  }
-
-  applyTimeSettings(dashboard: Dashboard) {
-    if (this.routeParams.startTime && this.routeParams.endTime) {
-      dashboard.dashboardTimeSettings = {
-        startTime: this.routeParams.startTime * 1,
-        endTime: this.routeParams.endTime * 1,
-        dynamicSelection: -1
-      };
-    } else if (!dashboard.dashboardTimeSettings) {
-      const currentTime = new Date().getTime();
-      dashboard.dashboardTimeSettings = {
-        startTime: currentTime - 100000 * 60000,
-        endTime: currentTime,
-        dynamicSelection: -1
-      };
-    }
-  }
-
-  findAndSelectDashboard(dashboardId: string) {
-    const currentDashboard = this.dataViewDashboards.find(d => d._id === dashboardId);
-    this.selectDashboard(this.dataViewDashboards.indexOf(currentDashboard) + 1);
-  }
-
-  getDashboards(currentDashboardId?: string) {
-    this.dashboardsLoaded = false;
-    this.dataViewService.getDataViews().subscribe(data => {
-      this.dataViewDashboards = data.sort((a, b) => a.name.localeCompare(b.name));
-      if (currentDashboardId) {
-        this.findAndSelectDashboard(currentDashboardId);
-      } else if (this.routeParams.dashboardId) {
-        this.findAndSelectDashboard(this.routeParams.dashboardId);
-      } else {
-        this.selectedIndex = 0;
-      }
-      this.dashboardsLoaded = true;
-    });
-  }
-
-  triggerEditMode() {
-    this.editMode = true;
-  }
-
-  deleteDashboard(dashboard: Dashboard) {
-    this.dashboardService.deleteDashboard(dashboard).subscribe(result => {
-      this.getDashboards();
-    });
-  }
-
-  resetDashboardChanges() {
-    this.getDashboards(this.selectedDataViewDashboard._id);
-  }
-}
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts b/ui/src/app/data-explorer/data-explorer.module.ts
index 79819b3..f0702a2 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -50,8 +50,7 @@
 } from '@streampipes/platform-services';
 import { CoreUiModule } from '../core-ui/core-ui.module';
 import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
-import { DataDownloadDialog } from './components/datadownloadDialog/dataDownload.dialog';
-import { DataExplorerDashboardGridComponent } from './components/grid/data-explorer-dashboard-grid.component';
+import { DataExplorerDashboardGridComponent } from './components/widget-view/grid-view/data-explorer-dashboard-grid.component';
 import { DataExplorerDashboardOverviewComponent } from './components/overview/data-explorer-dashboard-overview.component';
 import { DataExplorerDashboardPanelComponent } from './components/panel/data-explorer-dashboard-panel.component';
 import { TimeRangeSelectorComponent } from './components/time-selector/timeRangeSelector.component';
@@ -64,7 +63,6 @@
 import { NoDataInDateRangeComponent } from './components/widgets/utils/no-data/no-data-in-date-range.component';
 import { SelectPropertiesComponent } from './components/widgets/utils/select-properties/select-properties.component';
 import { SelectColorPropertiesComponent } from './components/widgets/utils/select-color-properties/select-color-properties.component';
-import { DataExplorerComponent } from './data-explorer.component';
 import { DataExplorerEditDataViewDialogComponent } from './dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component';
 import { RefreshDashboardService } from './services/refresh-dashboard.service';
 import { ResizeService } from './services/resize.service';
@@ -100,6 +98,10 @@
 import { NgxEchartsModule } from 'ngx-echarts';
 import { TooMuchDataComponent } from './components/widgets/utils/too-much-data/too-much-data.component';
 import { SpValueHeatmapComponent } from './components/widgets/distribution-chart/value-heatmap/value-heatmap.component';
+import { RouterModule } from '@angular/router';
+import { DataExplorerDashboardSlideViewComponent } from './components/widget-view/slide-view/data-explorer-dashboard-slide-view.component';
+import { SharedUiModule } from '@streampipes/shared-ui';
+import { DataExplorerPanelCanDeactivateGuard } from './data-explorer-panel.can-deactivate.guard';
 
 export const MY_NATIVE_FORMATS = {
   fullPickerInput: {
@@ -145,22 +147,39 @@
     MatSlideToggleModule,
     MatChipsModule,
     PlatformServicesModule,
+    SharedUiModule,
     NgxEchartsModule.forRoot({
-      /**
-       * This will import all modules from echarts.
-       * If you only need custom modules,
-       * please refer to [Custom Build] section.
-       */
       echarts: () => import('echarts'),
     }),
+    RouterModule.forChild([
+      {
+        path: 'dataexplorer',
+        children: [
+          {
+            path: '',
+            component: DataExplorerDashboardOverviewComponent
+          },
+          {
+            path: ':id',
+            component: DataExplorerDashboardPanelComponent,
+            canDeactivate: [DataExplorerPanelCanDeactivateGuard]
+          },
+          {
+            path: ':id/:startTime/:endTime',
+            component: DataExplorerDashboardPanelComponent,
+            canDeactivate: [DataExplorerPanelCanDeactivateGuard]
+          }
+        ]
+      }
+    ]),
+
   ],
   declarations: [
     AggregateConfigurationComponent,
-    DataDownloadDialog,
-    DataExplorerComponent,
     DataExplorerDashboardGridComponent,
     DataExplorerDashboardOverviewComponent,
     DataExplorerDashboardPanelComponent,
+    DataExplorerDashboardSlideViewComponent,
     DataExplorerDashboardWidgetComponent,
     DataExplorerDesignerPanelComponent,
     DataExplorerEditDataViewDialogComponent,
@@ -216,7 +235,6 @@
     }
   ],
   exports: [
-    DataExplorerComponent
   ]
 })
 export class DataExplorerModule {
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/data-explorer/data-explorer.routes.ts
similarity index 81%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/src/app/data-explorer/data-explorer.routes.ts
index a375af7..7c3df23 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/data-explorer/data-explorer.routes.ts
@@ -16,7 +16,10 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
-}
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
 
+export class SpDataExplorerRoutes {
+
+  static BASE: SpBreadcrumbItem = {label: 'Data Views', link: ['dataexplorer']};
+
+}
diff --git a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.html b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.html
index 20a5501..d64581e 100644
--- a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.html
+++ b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.html
@@ -30,6 +30,16 @@
                     <mat-label>Description</mat-label>
                     <input matInput [(ngModel)]="dashboard.description">
                 </mat-form-field>
+                <label>Default view mode</label>
+                <mat-radio-group
+                        [(ngModel)]="dashboard.dashboardGeneralSettings.defaultViewMode">
+                    <mat-radio-button class="view-radio-button" [value]="'grid'">
+                        Grid View
+                    </mat-radio-button>
+                    <mat-radio-button class="view-radio-button" [value]="'slide'">
+                        Slide View
+                    </mat-radio-button>
+                </mat-radio-group>
                 <!--<mat-checkbox [(ngModel)]="dashboard.displayHeader">Show name and description in dashboard</mat-checkbox>-->
 
             </div>
diff --git a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.scss b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.scss
index 2c22a1c..ff0c283 100644
--- a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.scss
+++ b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.scss
@@ -30,3 +30,14 @@
 .mr-10 {
     margin-right: 10px;
 }
+
+.view-radio-group {
+    display: flex;
+    flex-direction: column;
+    margin: 15px 0;
+    align-items: flex-start;
+}
+
+.view-radio-button {
+    margin: 5px;
+}
diff --git a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.ts b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.ts
index 1af1ab8..8d5a3fc 100644
--- a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.ts
+++ b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component.ts
@@ -36,7 +36,9 @@
   }
 
   ngOnInit() {
-
+    if (!this.dashboard.dashboardGeneralSettings.defaultViewMode) {
+      this.dashboard.dashboardGeneralSettings.defaultViewMode = 'grid';
+    }
   }
 
   onCancel(): void {
diff --git a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
index 3be8ef4..edf8e0d 100644
--- a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
+++ b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
@@ -34,7 +34,7 @@
 import { ShepherdService } from '../../../services/tour/shepherd.service';
 import { PipelineElementConfig, PipelineElementUnion } from '../../model/editor.model';
 import { ObjectProvider } from '../../services/object-provider.service';
-import { DialogService, PanelType, ConfirmDialogComponent } from '@streampipes/shared-ui';
+import { ConfirmDialogComponent, DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
 import { SavePipelineComponent } from '../../dialog/save-pipeline/save-pipeline.component';
 import { MatDialog } from '@angular/material/dialog';
 import { EditorService } from '../../services/editor.service';
@@ -45,6 +45,8 @@
 import { PipelineComponent } from '../pipeline/pipeline.component';
 import { forkJoin } from 'rxjs';
 import { PipelineElementDiscoveryComponent } from '../../dialog/pipeline-element-discovery/pipeline-element-discovery.component';
+import { SpPipelineRoutes } from '../../../pipelines/pipelines.routes';
+import { Router } from '@angular/router';
 
 
 @Component({
@@ -106,7 +108,9 @@
                 private dialog: MatDialog,
                 private ngZone: NgZone,
                 private pipelineElementDraggedService: PipelineElementDraggedService,
-                private pipelineCanvasMetadataService: PipelineCanvasMetadataService) {
+                private pipelineCanvasMetadataService: PipelineCanvasMetadataService,
+                private breadcrumbService: SpBreadcrumbService,
+                private router: Router) {
 
         this.selectMode = true;
         this.currentZoomLevel = 1;
@@ -249,6 +253,7 @@
         pipelineRequest.subscribe(pipelineResp => {
                 const pipeline = pipelineResp;
                 this.currentPipelineName = pipeline.name;
+                this.breadcrumbService.updateBreadcrumb([SpPipelineRoutes.BASE, {label: pipeline.name}, {label: 'Modify'}]);
                 this.currentPipelineDescription = pipeline.description;
                 this.rawPipelineModel = this.jsplumbService.makeRawPipeline(pipeline, false);
                 canvasRequest.subscribe(canvasResp => {
diff --git a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss
index 8ede964..be1bab1 100644
--- a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss
+++ b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss
@@ -25,7 +25,7 @@
 }
 
 .icon-stand {
-  max-height: calc(100vh - 118px);
+  max-height: calc(100vh - 148px);
   overflow-y: auto;
   background: var(--color-bg-1);
   margin-top: 5px;
@@ -110,6 +110,7 @@
   border-radius: 3px;
   font-size: small;
   background: var(--color-primary);
+  color: var(--color-accent);
 }
 
 .sort-option {
diff --git a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.html b/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.html
deleted file mode 100644
index 97cd141..0000000
--- a/ui/src/app/editor/components/pipeline-element-template-config/pipeline-element-template-config.component.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div class="p-15">
-    <div fxFlex="100" fxLayout="column">
-        <h4>Basics</h4>
-        <mat-form-field fxFlex>
-            <mat-label>Template name</mat-label>
-            <input [(ngModel)]="template.templateName" matInput name="templateName" class="sp" required/>
-        </mat-form-field>
-        <mat-form-field fxFlex>
-            <mat-label>Template description</mat-label>
-            <input [(ngModel)]="template.templateDescription" matInput name="templateDescription" class="sp"
-                   required/>
-        </mat-form-field>
-        <mat-checkbox class="sp" color="primary">Make available as pipeline element</mat-checkbox>
-        <mat-divider class="divider"></mat-divider>
-        <h4>Configuration</h4>
-        <div fxLayout="column" *ngFor="let config of cachedPipelineElement.staticProperties"
-             class="static-property-panel static-property-panel-border">
-            <div fxLayout="row">
-                <div fxFlex="50">
-                    {{config.label}}
-                </div>
-                <div fxFlex="50">
-                    <div fxLayout="column">
-                        <mat-checkbox [checked]="templateConfigs.has(config.internalName)"
-                                      (change)="handleSelection(config)" name="store" class="sp" color="primary">Store
-                            as template
-                        </mat-checkbox>
-<!--                        <mat-checkbox *ngIf="templateConfigs.has(config.internalName)"-->
-<!--                                      (click)="toggleViewPermission(config)" name="displayed"-->
-<!--                                      class="sp" color="primary">Users can view-->
-<!--                        </mat-checkbox>-->
-<!--                        <mat-checkbox *ngIf="templateConfigs.has(config.internalName)"-->
-<!--                                      (click)="toggleEditPermission(config)" name="editable"-->
-<!--                                      class="sp" color="primary">Users can modify-->
-<!--                        </mat-checkbox>-->
-                    </div>
-                </div>
-            </div>
-
-        </div>
-    </div>
-</div>
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.ts b/ui/src/app/editor/components/pipeline/pipeline.component.ts
index bcc2690..719eefa 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.ts
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.ts
@@ -338,8 +338,9 @@
                   this.showCustomizeDialog(pe);
                 } else {
                   (pe.payload as InvocablePipelineElementUnion).configured = true;
-                  this.pipelineStyleService.updatePeConfigurationStatus(pe, PipelineElementConfigurationStatus.INCOMPLETE);
+                  this.pipelineStyleService.updatePeConfigurationStatus(pe, PipelineElementConfigurationStatus.OK);
                   this.announceConfiguredElement(pe);
+                  this.triggerPipelineCacheUpdate();
                 }
               }
             } else {
@@ -408,11 +409,13 @@
 
   isCustomOutput(pe) {
     let custom = false;
-    pe.payload.outputStrategies.forEach(strategy => {
-      if (strategy instanceof CustomOutputStrategy) {
-        custom = true;
-      }
-    });
+    if (pe.payload instanceof DataProcessorInvocation) {
+      pe.payload.outputStrategies.forEach(strategy => {
+        if (strategy instanceof CustomOutputStrategy) {
+          custom = true;
+        }
+      });
+    }
     return custom;
   }
 
diff --git a/ui/src/app/editor/dialog/customize/customize.component.html b/ui/src/app/editor/dialog/customize/customize.component.html
index 78c8589..9e5e04f 100644
--- a/ui/src/app/editor/dialog/customize/customize.component.html
+++ b/ui/src/app/editor/dialog/customize/customize.component.html
@@ -21,9 +21,10 @@
         <div fxFlex="100" fxLayout="column">
             <div style="border-bottom:1px solid #ccc;padding:10px;" fxLayout="row" class="sp-tab-bg">
                 <div fxFlex fxLayoutAlign="start center" *ngIf="availableTemplates && availableTemplates.length > 0">
-                    <mat-form-field class="form-field" floatLabel="never">
+                    <mat-form-field class="form-field" floatLabel="never" color="accent">
                         <mat-label>Use template</mat-label>
-                        <mat-select (selectionChange)="loadTemplate($event)" [(value)]="selectedTemplate">
+                        <mat-select (selectionChange)="loadTemplate($event)"
+                                    [(value)]="selectedTemplate">
                             <mat-option>--</mat-option>
                             <mat-option [value]="template" *ngFor="let template of availableTemplates">
                                 {{template.templateName}}
@@ -72,8 +73,8 @@
                         </div>
                     </div>
                     <div fxLayout="column" *ngIf="templateMode">
-                        <pipeline-element-template-config [cachedPipelineElement]="cachedPipelineElement"
-                        [template]="template" [templateConfigs]="templateConfigs">
+                        <pipeline-element-template-config [staticProperties]="cachedPipelineElement.staticProperties"
+                        [template]="template" [templateConfigs]="templateConfigs" [appId]="cachedPipelineElement.appId">
                         </pipeline-element-template-config>
                     </div>
                 </div>
diff --git a/ui/src/app/editor/dialog/customize/customize.component.ts b/ui/src/app/editor/dialog/customize/customize.component.ts
index 1dfd772..f042ccf 100644
--- a/ui/src/app/editor/dialog/customize/customize.component.ts
+++ b/ui/src/app/editor/dialog/customize/customize.component.ts
@@ -205,9 +205,6 @@
           this.cachedPipelineElement = pe as InvocablePipelineElementUnion;
         });
       }
-
     }
   }
-
-
 }
diff --git a/ui/src/app/editor/editor.component.ts b/ui/src/app/editor/editor.component.ts
index 76caa68..d4cf227 100644
--- a/ui/src/app/editor/editor.component.ts
+++ b/ui/src/app/editor/editor.component.ts
@@ -20,7 +20,7 @@
 import { EditorService } from './services/editor.service';
 import { DataSourceDescription, PipelineElementService, SpDataStream } from '@streampipes/platform-services';
 import { PipelineElementConfig, PipelineElementUnion } from './model/editor.model';
-import { PanelType, DialogService } from '@streampipes/shared-ui';
+import { DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
 import { WelcomeTourComponent } from './dialog/welcome-tour/welcome-tour.component';
 import { MissingElementsForTutorialComponent } from './dialog/missing-elements-for-tutorial/missing-elements-for-tutorial.component';
 import { ShepherdService } from '../services/tour/shepherd.service';
@@ -28,6 +28,7 @@
 import { AuthService } from '../services/auth.service';
 import { zip } from 'rxjs';
 import { AppConstants } from '../services/app.constants';
+import { SpPipelineRoutes } from '../pipelines/pipelines.routes';
 
 @Component({
   selector: 'editor',
@@ -56,13 +57,16 @@
               private dialogService: DialogService,
               private shepherdService: ShepherdService,
               private activatedRoute: ActivatedRoute,
-              private appConstants: AppConstants) {
+              private appConstants: AppConstants,
+              private breadcrumbService: SpBreadcrumbService) {
   }
 
   ngOnInit() {
-    this.activatedRoute.queryParams.subscribe(params => {
-      if (params['pipeline']) {
-        this.currentModifiedPipelineId = params['pipeline'];
+    this.activatedRoute.params.subscribe(params => {
+      if (params.pipelineId) {
+        this.currentModifiedPipelineId = params.pipelineId;
+      } else {
+        this.breadcrumbService.updateBreadcrumb([SpPipelineRoutes.BASE, {label: 'New Pipeline'}]);
       }
     });
     zip(this.pipelineElementService.getDataStreams(),
diff --git a/ui/src/app/editor/editor.module.ts b/ui/src/app/editor/editor.module.ts
index 266b0fd..284ce1f 100644
--- a/ui/src/app/editor/editor.module.ts
+++ b/ui/src/app/editor/editor.module.ts
@@ -29,13 +29,8 @@
 import { PipelineElementIconStandComponent } from './components/pipeline-element-icon-stand/pipeline-element-icon-stand.component';
 import { PipelineAssemblyComponent } from './components/pipeline-assembly/pipeline-assembly.component';
 import { PipelineElementComponent } from './components/pipeline-element/pipeline-element.component';
-import { PipelinePositioningService } from './services/pipeline-positioning.service';
-import { JsplumbService } from './services/jsplumb.service';
-import { JsplumbConfigService } from './services/jsplumb-config.service';
 import { PipelineEditorService } from './services/pipeline-editor.service';
-import { PipelineValidationService } from './services/pipeline-validation.service';
 import { PipelineComponent } from './components/pipeline/pipeline.component';
-import { ObjectProvider } from './services/object-provider.service';
 import { PipelineElementOptionsComponent } from './components/pipeline-element-options/pipeline-element-options.component';
 import { PipelineElementRecommendationService } from './services/pipeline-element-recommendation.service';
 import { CustomizeComponent } from './dialog/customize/customize.component';
@@ -57,20 +52,16 @@
 import { PropertySelectionComponent } from './components/output-strategy/property-selection/property-selection.component';
 import { UserDefinedOutputStrategyComponent } from './components/output-strategy/user-defined-output/user-defined-output.component';
 import { ConnectModule } from '../connect/connect.module';
-import { PipelineElementTemplateConfigComponent } from './components/pipeline-element-template-config/pipeline-element-template-config.component';
 import { EnabledPipelineElementFilter } from './filter/enabled-pipeline-element.filter';
 import { PipelineElementDraggedService } from './services/pipeline-element-dragged.service';
 import { PipelineCanvasScrollingService } from './services/pipeline-canvas-scrolling.service';
-import { JsplumbEndpointService } from './services/jsplumb-endpoint.service';
-import { JsplumbFactoryService } from './services/jsplumb-factory.service';
 import { PipelineElementPreviewComponent } from './components/pipeline-element-preview/pipeline-element-preview.component';
 import { PipelineElementDiscoveryComponent } from './dialog/pipeline-element-discovery/pipeline-element-discovery.component';
-import { PipelineStyleService } from './services/pipeline-style.service';
 import { PlatformServicesModule } from '@streampipes/platform-services';
 import { PipelineElementIconStandRowComponent } from './components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component';
 import { PipelineElementTypeFilterPipe } from './services/pipeline-element-type-filter.pipe';
-import { PipelineElementNameFilterPipe } from "./services/pipeline-element-name-filter.pipe";
-import { PipelineElementGroupFilterPipe } from "./services/pipeline-element-group-filter.pipe";
+import { PipelineElementNameFilterPipe } from './services/pipeline-element-name-filter.pipe';
+import { PipelineElementGroupFilterPipe } from './services/pipeline-element-group-filter.pipe';
 
 
 @NgModule({
@@ -113,7 +104,6 @@
         PipelineElementOptionsComponent,
         PipelineElementPreviewComponent,
         PipelineElementRecommendationComponent,
-        PipelineElementTemplateConfigComponent,
         PipelineElementTypeFilterPipe,
         PipelineComponent,
         PropertySelectionComponent,
@@ -122,20 +112,7 @@
         WelcomeTourComponent
     ],
     providers: [
-        EditorService,
         SemanticTypeUtilsService,
-        JsplumbFactoryService,
-        JsplumbEndpointService,
-        JsplumbService,
-        JsplumbConfigService,
-        ObjectProvider,
-        PipelineCanvasScrollingService,
-        PipelineElementDraggedService,
-        PipelineEditorService,
-        PipelinePositioningService,
-        PipelineStyleService,
-        PipelineValidationService,
-        PipelineElementRecommendationService,
         SafeCss,
     ],
     exports: [
diff --git a/ui/src/app/editor/services/editor.service.ts b/ui/src/app/editor/services/editor.service.ts
index fcde9ad..99c19e3 100644
--- a/ui/src/app/editor/services/editor.service.ts
+++ b/ui/src/app/editor/services/editor.service.ts
@@ -37,7 +37,7 @@
 import { HelpComponent } from '../dialog/help/help.component';
 import { map } from 'rxjs/operators';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class EditorService {
 
     private pipelineElementConfigured = new Subject<string>();
diff --git a/ui/src/app/editor/services/jsplumb-config.service.ts b/ui/src/app/editor/services/jsplumb-config.service.ts
index f43742b..76d0f38 100644
--- a/ui/src/app/editor/services/jsplumb-config.service.ts
+++ b/ui/src/app/editor/services/jsplumb-config.service.ts
@@ -22,7 +22,7 @@
 import { EndpointTypeDescriptor } from '@jsplumb/core';
 import { ArrowOverlayOptions } from '@jsplumb/common';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class JsplumbConfigService {
 
   constructor() {
diff --git a/ui/src/app/editor/services/jsplumb-endpoint.service.ts b/ui/src/app/editor/services/jsplumb-endpoint.service.ts
index fc554e4..e9786dd 100644
--- a/ui/src/app/editor/services/jsplumb-endpoint.service.ts
+++ b/ui/src/app/editor/services/jsplumb-endpoint.service.ts
@@ -19,7 +19,7 @@
 import { Injectable } from '@angular/core';
 import { JsplumbConfigService } from './jsplumb-config.service';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class JsplumbEndpointService {
 
   constructor(private jsplumbConfigService: JsplumbConfigService) {
diff --git a/ui/src/app/editor/services/jsplumb-factory.service.ts b/ui/src/app/editor/services/jsplumb-factory.service.ts
index a0f98c9..a895e72 100644
--- a/ui/src/app/editor/services/jsplumb-factory.service.ts
+++ b/ui/src/app/editor/services/jsplumb-factory.service.ts
@@ -23,7 +23,7 @@
 import { PipelineElementDraggedService } from './pipeline-element-dragged.service';
 import { JsplumbConfigService } from './jsplumb-config.service';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class JsplumbFactoryService {
 
     pipelineEditorInstance: BrowserJsPlumbInstance;
diff --git a/ui/src/app/editor/services/jsplumb.service.ts b/ui/src/app/editor/services/jsplumb.service.ts
index efb4390..127d608 100644
--- a/ui/src/app/editor/services/jsplumb.service.ts
+++ b/ui/src/app/editor/services/jsplumb.service.ts
@@ -38,7 +38,7 @@
 import { JsplumbFactoryService } from './jsplumb-factory.service';
 import { EditorService } from './editor.service';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class JsplumbService {
 
   idCounter = 0;
@@ -98,7 +98,8 @@
           pipelineElementConfig.payload,
           true,
           false);
-      }, 100);
+        this.getBridge(false).repaintEverything();
+      }, 10);
     }
 
   }
diff --git a/ui/src/app/editor/services/object-provider.service.ts b/ui/src/app/editor/services/object-provider.service.ts
index 9a60865..95375ed 100644
--- a/ui/src/app/editor/services/object-provider.service.ts
+++ b/ui/src/app/editor/services/object-provider.service.ts
@@ -23,7 +23,7 @@
 import { EditorService } from './editor.service';
 import { JsplumbFactoryService } from './jsplumb-factory.service';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class ObjectProvider {
 
     constructor(private restApi: RestApi,
diff --git a/ui/src/app/editor/services/pipeline-canvas-scrolling.service.ts b/ui/src/app/editor/services/pipeline-canvas-scrolling.service.ts
index 5be904d..764b1f7 100644
--- a/ui/src/app/editor/services/pipeline-canvas-scrolling.service.ts
+++ b/ui/src/app/editor/services/pipeline-canvas-scrolling.service.ts
@@ -19,7 +19,7 @@
 import { Injectable } from '@angular/core';
 import { Subject } from 'rxjs';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class PipelineCanvasScrollingService {
 
   public canvasScrollXSubject: Subject<number> = new Subject<number>();
diff --git a/ui/src/app/editor/services/pipeline-editor.service.ts b/ui/src/app/editor/services/pipeline-editor.service.ts
index 1057188..2e3dfeb 100644
--- a/ui/src/app/editor/services/pipeline-editor.service.ts
+++ b/ui/src/app/editor/services/pipeline-editor.service.ts
@@ -18,7 +18,7 @@
 
 import { Injectable } from '@angular/core';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class PipelineEditorService {
 
     constructor() {
diff --git a/ui/src/app/editor/services/pipeline-element-dragged.service.ts b/ui/src/app/editor/services/pipeline-element-dragged.service.ts
index 16ae51e..c5c2bc5 100644
--- a/ui/src/app/editor/services/pipeline-element-dragged.service.ts
+++ b/ui/src/app/editor/services/pipeline-element-dragged.service.ts
@@ -20,7 +20,7 @@
 import { Subject } from 'rxjs';
 import { PipelineElementPosition } from '../model/editor.model';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class PipelineElementDraggedService {
 
   public pipelineElementMovedSubject: Subject<PipelineElementPosition> = new Subject<PipelineElementPosition>();
diff --git a/ui/src/app/editor/services/pipeline-element-recommendation.service.ts b/ui/src/app/editor/services/pipeline-element-recommendation.service.ts
index 129c159..ae676f9 100644
--- a/ui/src/app/editor/services/pipeline-element-recommendation.service.ts
+++ b/ui/src/app/editor/services/pipeline-element-recommendation.service.ts
@@ -24,7 +24,7 @@
   SpDataStream
 } from '@streampipes/platform-services';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class PipelineElementRecommendationService {
 
     constructor() {
diff --git a/ui/src/app/editor/services/pipeline-positioning.service.ts b/ui/src/app/editor/services/pipeline-positioning.service.ts
index 2293d0b..1f8b281 100644
--- a/ui/src/app/editor/services/pipeline-positioning.service.ts
+++ b/ui/src/app/editor/services/pipeline-positioning.service.ts
@@ -33,7 +33,7 @@
 import { ObjectProvider } from './object-provider.service';
 import { Connection } from '@jsplumb/core';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class PipelinePositioningService {
 
   constructor(private jsplumbService: JsplumbService,
diff --git a/ui/src/app/editor/services/pipeline-style.service.ts b/ui/src/app/editor/services/pipeline-style.service.ts
index 42a14f3..9d6dabe 100644
--- a/ui/src/app/editor/services/pipeline-style.service.ts
+++ b/ui/src/app/editor/services/pipeline-style.service.ts
@@ -23,7 +23,7 @@
 import { JsplumbFactoryService } from './jsplumb-factory.service';
 import { PipelineElementConfig, PipelineElementConfigurationStatus } from '../model/editor.model';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class PipelineStyleService {
 
   constructor(private jsPlumbConfigService: JsplumbConfigService,
diff --git a/ui/src/app/editor/services/pipeline-validation.service.ts b/ui/src/app/editor/services/pipeline-validation.service.ts
index 779b83e..e3607fa 100644
--- a/ui/src/app/editor/services/pipeline-validation.service.ts
+++ b/ui/src/app/editor/services/pipeline-validation.service.ts
@@ -25,7 +25,7 @@
 import { UserErrorMessage } from '../../core-model/base/UserErrorMessage';
 import { Connection } from '@jsplumb/core';
 
-@Injectable()
+@Injectable({providedIn: 'root'})
 export class PipelineValidationService {
 
     errorMessages: any = [];
diff --git a/ui/src/app/files/components/file-overview/file-overview.component.html b/ui/src/app/files/components/file-overview/file-overview.component.html
index ea985b3..051d7b9 100644
--- a/ui/src/app/files/components/file-overview/file-overview.component.html
+++ b/ui/src/app/files/components/file-overview/file-overview.component.html
@@ -16,45 +16,48 @@
   ~
   -->
 
-<div fxFlex="100" fxLayout="column" *ngIf="filesAvailable" style="margin:1px;">
-    <table fxFlex="100" mat-table [dataSource]="dataSource" style="width: 100%;">
-        <ng-container matColumnDef="filename">
-            <th mat-header-cell *matHeaderCellDef> Filename</th>
-            <td mat-cell *matCellDef="let fileMetadata">
-                <h4>{{fileMetadata.originalFilename}}</h4>
-            </td>
-        </ng-container>
-        <ng-container matColumnDef="filetype">
-            <th mat-header-cell *matHeaderCellDef> Filetype</th>
-            <td mat-cell *matCellDef="let fileMetadata">
-                <span class="filetype-container">{{fileMetadata.filetype}}</span>
-            </td>
-        </ng-container>
-        <ng-container matColumnDef="uploaded">
-            <th mat-header-cell *matHeaderCellDef> Uploaded</th>
-            <td mat-cell *matCellDef="let fileMetadata">
-                <h5>{{fileMetadata.createdAt | date:'dd.MM.yyyy HH:mm'}}</h5>
-            </td>
-        </ng-container>
+<div fxFlex="100" fxLayout="column" style="margin:1px;">
+    <div fxLayout="column" fxFlex="100" *ngIf="filesAvailable">
+        <table fxFlex="100" mat-table [dataSource]="dataSource" style="width: 100%;">
+            <ng-container matColumnDef="filename">
+                <th mat-header-cell *matHeaderCellDef> Filename</th>
+                <td mat-cell *matCellDef="let fileMetadata">
+                    <h4>{{fileMetadata.originalFilename}}</h4>
+                </td>
+            </ng-container>
+            <ng-container matColumnDef="filetype">
+                <th mat-header-cell *matHeaderCellDef> Filetype</th>
+                <td mat-cell *matCellDef="let fileMetadata">
+                    <span class="filetype-container">{{fileMetadata.filetype}}</span>
+                </td>
+            </ng-container>
+            <ng-container matColumnDef="uploaded">
+                <th mat-header-cell *matHeaderCellDef> Uploaded</th>
+                <td mat-cell *matCellDef="let fileMetadata">
+                    <h5>{{fileMetadata.createdAt | date:'dd.MM.yyyy HH:mm'}}</h5>
+                </td>
+            </ng-container>
 
-        <ng-container matColumnDef="action">
-            <th mat-header-cell *matHeaderCellDef> Action</th>
-            <td mat-cell *matCellDef="let fileMetadata">
-                    <button color="accent" mat-button mat-icon-button matTooltip="Delete file" matTooltipPosition="above"
+            <ng-container matColumnDef="action">
+                <th mat-header-cell *matHeaderCellDef> Action</th>
+                <td mat-cell *matCellDef="let fileMetadata">
+                    <button color="accent" mat-button mat-icon-button matTooltip="Delete file"
+                            matTooltipPosition="above"
                             (click)="deleteFile(fileMetadata)" data-cy="delete">
                         <i class="material-icons">delete</i>
                     </button>
-            </td>
-        </ng-container>
+                </td>
+            </ng-container>
 
-        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
-        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+            <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
 
-    </table>
-    <div fxFlex="100" fxLayoutAlign="end end">
-        <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]="10"></mat-paginator>
+        </table>
+        <div fxFlex="100" fxLayoutAlign="end end">
+            <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]="10"></mat-paginator>
+        </div>
     </div>
-</div>
-<div fxFlex="100" fxLayout="column" fxLayoutAlign="center center" *ngIf="!filesAvailable">
-    <h5>(no files available)</h5>
+    <div fxFlex="100" fxLayout="column" fxLayoutAlign="center center" *ngIf="!filesAvailable">
+        <h5>(no files available)</h5>
+    </div>
 </div>
diff --git a/ui/src/app/files/components/file-overview/file-overview.component.scss b/ui/src/app/files/components/file-overview/file-overview.component.scss
index e37a83c..a1b1300 100644
--- a/ui/src/app/files/components/file-overview/file-overview.component.scss
+++ b/ui/src/app/files/components/file-overview/file-overview.component.scss
@@ -26,10 +26,10 @@
 }
 
 .mat-row:nth-child(even) {
-  background-color: var(--color-bg-2);
+  background-color: var(--color-bg-1);
 }
 .mat-row:nth-child(odd) {
-  background-color: var(--color-bg-3);
+  background-color: var(--color-bg-2);
 }
 
 .filetype-container {
diff --git a/ui/src/app/files/components/file-overview/file-overview.component.ts b/ui/src/app/files/components/file-overview/file-overview.component.ts
index 35f87a0..dda5d58 100644
--- a/ui/src/app/files/components/file-overview/file-overview.component.ts
+++ b/ui/src/app/files/components/file-overview/file-overview.component.ts
@@ -35,7 +35,7 @@
   dataSource: MatTableDataSource<FileMetadata>;
   filesAvailable = false;
 
-  @ViewChild(MatPaginator) paginator: MatPaginator;
+  paginator: MatPaginator;
   pageSize = 1;
 
   constructor(private filesService: FilesService,
@@ -44,13 +44,14 @@
   }
 
   ngOnInit() {
+    this.dataSource = new MatTableDataSource<FileMetadata>([]);
     this.refreshFiles();
   }
 
   refreshFiles() {
     this.filesService.getFileMetadata().subscribe(fm => {
-      this.dataSource = new MatTableDataSource<FileMetadata>(fm);
-      this.filesAvailable = true;
+     this.dataSource.data = fm;
+      this.filesAvailable = fm && fm.length > 0;
       setTimeout(() => {
         this.dataSource.paginator = this.paginator;
       });
@@ -77,4 +78,8 @@
       }
     });
   }
+
+  @ViewChild(MatPaginator) set content(paginator: MatPaginator) {
+    this.paginator = paginator;
+  }
 }
diff --git a/ui/src/app/files/dialog/file-upload/file-upload-dialog.component.html b/ui/src/app/files/dialog/file-upload/file-upload-dialog.component.html
index f5961a6..ed88a66 100644
--- a/ui/src/app/files/dialog/file-upload/file-upload-dialog.component.html
+++ b/ui/src/app/files/dialog/file-upload/file-upload-dialog.component.html
@@ -22,12 +22,12 @@
         <div fxFlex="100">
             <div fxFlex="100" style="margin:5px;width:100%">
                 <mat-form-field style="width: 95%" (click)="fileInput.click();" color="accent">
-                    <input matInput placeholder="File" disabled (value)="fileName">
+                    <input matInput placeholder="File" disabled (value)="fileNames">
                     <input #fileInput type="file" style="display:none;"
                            (change)="handleFileInput($event.target.files)"
-                           data-cy="sp-file-management-file-input">
+                           data-cy="sp-file-management-file-input" multiple>
                     <div>
-                        {{fileName}}
+                        <div fxLayout="column" *ngFor="let filename of fileNames">{{filename}}</div>
                         <mat-progress-bar mode="determinate" value="{{uploadStatus}}" *ngIf="uploadStatus > 0" color="accent"></mat-progress-bar>
                     </div>
                     <button color="accent" matSuffix
@@ -39,13 +39,20 @@
                         {{errorMessage}}
                     </mat-error>
                 </mat-form-field>
+                <button mat-button mat-raised-button class="mat-basic" (click)="removeFilesFromUpload()">Clear</button>
             </div>
         </div>
     </div>
     <mat-divider></mat-divider>
     <div class="sp-dialog-actions">
-        <button mat-button mat-raised-button color="accent" (click)="store()" data-cy="sp-file-management-store-file" style="margin-right:10px;">
-            Store file
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                (click)="store()"
+                [disabled]="fileNames.length === 0"
+                data-cy="sp-file-management-store-file"
+                style="margin-right:10px;">
+            Import files
         </button>
         <button mat-button mat-raised-button class="mat-basic" (click)="cancel()" style="margin-right:10px;">
             Cancel
diff --git a/ui/src/app/files/dialog/file-upload/file-upload-dialog.component.ts b/ui/src/app/files/dialog/file-upload/file-upload-dialog.component.ts
index d3a9e42..0df31b1 100644
--- a/ui/src/app/files/dialog/file-upload/file-upload-dialog.component.ts
+++ b/ui/src/app/files/dialog/file-upload/file-upload-dialog.component.ts
@@ -29,9 +29,9 @@
 export class FileUploadDialogComponent implements OnInit {
 
   inputValue: string;
-  fileName: string;
+  fileNames: string[] = [];
 
-  selectedUploadFile: File;
+  selectedUploadFiles: FileList;
 
   hasInput: boolean;
   errorMessage = 'Please enter a value';
@@ -46,29 +46,45 @@
   ngOnInit(): void {
   }
 
-  handleFileInput(files: any) {
-    this.selectedUploadFile = files[0];
-    this.fileName = this.selectedUploadFile.name;
+  handleFileInput(files: FileList) {
+    this.selectedUploadFiles = files;
+    for (let i = 0; i < files.length; i++) {
+      this.fileNames.push(files.item(i).name);
+    }
     this.uploadStatus = 0;
   }
 
+  removeFilesFromUpload(): void {
+    this.selectedUploadFiles = undefined;
+    this.fileNames = [];
+  }
+
   store() {
     this.uploadStatus = 0;
-    if (this.selectedUploadFile !== undefined) {
-      this.filesService.uploadFile(this.selectedUploadFile).subscribe(
-          event => {
-            if (event.type === HttpEventType.UploadProgress) {
-              this.uploadStatus = Math.round(100 * event.loaded / event.total);
-            } else if (event instanceof HttpResponse) {
-              this.dialogRef.close();
-            }
-          },
-          error => {
-          },
-      );
+    if (this.selectedUploadFiles.length > 0) {
+      this.uploadFile(0);
     }
   }
 
+  uploadFile(index: number): void {
+    this.filesService.uploadFile(this.selectedUploadFiles.item(index)).subscribe(
+      event => {
+        if (event.type === HttpEventType.UploadProgress) {
+          this.uploadStatus = Math.round(100 * event.loaded / event.total);
+        } else if (event instanceof HttpResponse) {
+          index++;
+          if (index === (this.selectedUploadFiles.length)) {
+            this.dialogRef.close();
+          } else {
+            this.uploadFile(index);
+          }
+        }
+      },
+      error => {
+      },
+    );
+  }
+
   cancel() {
     this.dialogRef.close();
   }
diff --git a/ui/src/app/files/files.component.html b/ui/src/app/files/files.component.html
index 52264e7..10e701f 100644
--- a/ui/src/app/files/files.component.html
+++ b/ui/src/app/files/files.component.html
@@ -16,40 +16,25 @@
   ~
   -->
 
-<div fxLayout="column" class="page-container">
-    <div fxLayout="row" style="padding:0;" class="sp-tab-bg">
-        <div fxFlex="100" class="page-container-nav">
-            <div fxFlex="100" fxLayout="row">
-                <div fxFlex fxLayoutAlign="start center">
-                    <mat-tab-group color="accent">
-                        <mat-tab label="Files"></mat-tab>
-                    </mat-tab-group>
-                </div>
-            </div>
-        </div>
+<sp-basic-view [showBackLink]="false" [padding]="true">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <button mat-button mat-raised-button color="accent"
+                (click)="openFileUploadDialog()"
+                data-cy="sp-open-file-upload-dialog"
+                class="mr-10">
+            <i class="material-icons">cloud_upload</i>
+            &nbsp;Upload new file
+        </button>
     </div>
-    <div fxLayout="row" class="fixed-height add-options sp-tab-bg">
-        <div class="add-options-item" fxLayoutAlign="start center" fxLayout="row" style="padding-left:5px;">
-            <div fxFlex="100" fxLayout="row">
-                <button mat-button mat-raised-button color="accent"
-                        (click)="openFileUploadDialog()"
-                        data-cy="sp-open-file-upload-dialog"
-                        class="mr-10">
-                    <i class="material-icons">cloud_upload</i>
-                    &nbsp;Upload new file
-                </button>
-            </div>
+
+    <div fxFlex="100" fxLayout="column">
+        <sp-basic-header-title-component title="My Files"></sp-basic-header-title-component>
+        <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+            <sp-basic-inner-panel [showTitle]="false" innerPadding="0" outerMargin="0" fxFlex="90" [hideToolbar]="true">
+                <sp-file-overview #fileOverviewComponent></sp-file-overview>
+            </sp-basic-inner-panel>
         </div>
     </div>
 
-    <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100">
-        <div class="assemblyOptions sp-blue-bg mt-20" style="padding:5px;">
-            <div fxLayout="row" fxLayoutAlign="start center">
-                <h4>My files</h4>
-            </div>
-        </div>
-        <div class="sp-blue-border">
-            <sp-file-overview #fileOverviewComponent></sp-file-overview>
-        </div>
-    </div>
-</div>
+</sp-basic-view>
diff --git a/ui/src/app/files/files.component.ts b/ui/src/app/files/files.component.ts
index bee4a33..4c5afe0 100644
--- a/ui/src/app/files/files.component.ts
+++ b/ui/src/app/files/files.component.ts
@@ -17,8 +17,9 @@
  */
 
 import { Component, OnInit, ViewChild } from '@angular/core';
-import { DialogService, PanelType } from '@streampipes/shared-ui';
+import { DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
 import { FileUploadDialogComponent } from './dialog/file-upload/file-upload-dialog.component';
+import { SpFilesRoutes } from './files.routes';
 
 @Component({
   templateUrl: './files.component.html',
@@ -28,12 +29,13 @@
 
   @ViewChild('fileOverviewComponent') fileOverviewComponent;
 
-  constructor(private dialogService: DialogService) {
+  constructor(private dialogService: DialogService,
+              private breadcrumbService: SpBreadcrumbService) {
 
   }
 
   ngOnInit() {
-
+    this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpFilesRoutes.BASE));
   }
 
   openFileUploadDialog() {
diff --git a/ui/src/app/files/files.module.ts b/ui/src/app/files/files.module.ts
index 7bccd09..7eb7b8d 100644
--- a/ui/src/app/files/files.module.ts
+++ b/ui/src/app/files/files.module.ts
@@ -39,36 +39,49 @@
 import { MatChipsModule } from '@angular/material/chips';
 import { MatTooltipModule } from '@angular/material/tooltip';
 import { PlatformServicesModule } from '@streampipes/platform-services';
+import { RouterModule } from '@angular/router';
+import { SharedUiModule } from '@streampipes/shared-ui';
 
 @NgModule({
-    imports: [
-        CommonModule,
-        CoreUiModule,
-        FlexLayoutModule,
-        FormsModule,
-        ReactiveFormsModule,
-        MatButtonModule,
-        MatChipsModule,
-        MatFormFieldModule,
-        MatGridListModule,
-        MatIconModule,
-        MatInputModule,
-        MatDividerModule,
-        MatListModule,
-        MatPaginatorModule,
-        MatProgressBarModule,
-        MatTableModule,
-        MatTabsModule,
-        MatTooltipModule,
-        PlatformServicesModule,
-        ServicesModule
-    ],
-    declarations: [
-        FilesComponent,
-        FileOverviewComponent,
-        FileUploadDialogComponent
-    ],
-    providers: []
+  imports: [
+    CommonModule,
+    CoreUiModule,
+    FlexLayoutModule,
+    FormsModule,
+    ReactiveFormsModule,
+    MatButtonModule,
+    MatChipsModule,
+    MatFormFieldModule,
+    MatGridListModule,
+    MatIconModule,
+    MatInputModule,
+    MatDividerModule,
+    MatListModule,
+    MatPaginatorModule,
+    MatProgressBarModule,
+    MatTableModule,
+    MatTabsModule,
+    MatTooltipModule,
+    PlatformServicesModule,
+    ServicesModule,
+    SharedUiModule,
+    RouterModule.forChild([
+      {
+        path: 'files',
+        children: [
+          {
+            path: '',
+            component: FilesComponent
+          }]
+      }])
+
+  ],
+  declarations: [
+    FilesComponent,
+    FileOverviewComponent,
+    FileUploadDialogComponent
+  ],
+  providers: []
 })
 export class FilesModule {
 }
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/files/files.routes.ts
similarity index 77%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/files/files.routes.ts
index 58ba04b..10fb905 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/files/files.routes.ts
@@ -16,3 +16,10 @@
  *
  */
 
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+
+export class SpFilesRoutes {
+
+  static FILES_BASE_LINK = 'files';
+  static BASE: SpBreadcrumbItem = {label: 'File Management', link: [SpFilesRoutes.FILES_BASE_LINK]};
+}
diff --git a/ui/src/app/home/home.component.html b/ui/src/app/home/home.component.html
index c9699d9..bfad3d3 100644
--- a/ui/src/app/home/home.component.html
+++ b/ui/src/app/home/home.component.html
@@ -21,7 +21,7 @@
         <div fxFlex="100">

             <div fxFlex="100" fxLayout="column">

                 <div class="p-10 header-margin" fxLayoutAlign="center center">

-                    <div class="welcome-text">Welcome to {{appConstants.APP_NAME}}!</div>

+                    <div class="welcome-text">Welcome!</div>

                 </div>

                 <div fxLayout="column" fxFlex="100" class="home-margin">

                     <div fxFlex="100" fxLayoutAlign="start center">

diff --git a/ui/src/app/home/home.component.scss b/ui/src/app/home/home.component.scss
index 1bce66f..5cf0033 100644
--- a/ui/src/app/home/home.component.scss
+++ b/ui/src/app/home/home.component.scss
@@ -36,7 +36,7 @@
 }
 
 .welcome-text {
-    font-size: 30pt;
+    font-size: 26pt;
     font-weight: bold;
 }
 
diff --git a/ui/src/app/home/home.component.ts b/ui/src/app/home/home.component.ts
index e0fba3a..12ef848 100644
--- a/ui/src/app/home/home.component.ts
+++ b/ui/src/app/home/home.component.ts
@@ -16,27 +16,33 @@
  *

  */

 

-import { Component } from '@angular/core';

+import { Component, OnInit } from '@angular/core';

 import { DomSanitizer } from '@angular/platform-browser';

 import { HomeService } from './home.service';

 import { Router } from '@angular/router';

 import { AppConstants } from '../services/app.constants';

+import { SpBreadcrumbService } from '@streampipes/shared-ui';

 

 @Component({

     templateUrl: './home.component.html',

     styleUrls: ['./home.component.scss']

 })

-export class HomeComponent {

+export class HomeComponent implements OnInit {

 

     serviceLinks = [];

 

     constructor(private homeService: HomeService,

                 private sanitizer: DomSanitizer,

                 private router: Router,

-                public appConstants: AppConstants) {

+                public appConstants: AppConstants,

+                private breadcrumbService: SpBreadcrumbService) {

         this.serviceLinks = this.homeService.getFilteredServiceLinks();

     }

 

+    ngOnInit() {

+        this.breadcrumbService.updateBreadcrumb([]);

+    }

+

     getBackground(url) {

         return this.sanitizer.bypassSecurityTrustStyle(`url(${url})`);

     }

diff --git a/ui/src/app/info/info.component.ts b/ui/src/app/info/info.component.ts
index b734dc5..6a7c121 100644
--- a/ui/src/app/info/info.component.ts
+++ b/ui/src/app/info/info.component.ts
@@ -16,25 +16,29 @@
  *
  */
 
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { MatTabChangeEvent } from '@angular/material/tabs';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
 
 @Component({
-    templateUrl: './info.component.html',
-    styleUrls: ['./info.component.css']
+  templateUrl: './info.component.html',
+  styleUrls: ['./info.component.css']
 })
-export class InfoComponent {
+export class InfoComponent implements OnInit {
 
-    currentTabIndex = 0;
+  currentTabIndex = 0;
 
-    constructor() {
+  constructor(private breadcrumbService: SpBreadcrumbService) {
 
-    }
+  }
 
-    tabChanged(tabChangeEvent: MatTabChangeEvent): void {
-        this.currentTabIndex = tabChangeEvent.index;
-    }
+  ngOnInit() {
+    this.breadcrumbService.updateBreadcrumb([{label: 'Info'}]);
+  }
 
+  tabChanged(tabChangeEvent: MatTabChangeEvent): void {
+    this.currentTabIndex = tabChangeEvent.index;
+  }
 
 
 }
diff --git a/ui/src/app/notifications/notifications.component.ts b/ui/src/app/notifications/notifications.component.ts
index 33f9ce6..4d31082 100644
--- a/ui/src/app/notifications/notifications.component.ts
+++ b/ui/src/app/notifications/notifications.component.ts
@@ -26,6 +26,7 @@
 import { FreeTextStaticProperty, Pipeline, PipelineService } from '@streampipes/platform-services';
 import { AuthService } from '../services/auth.service';
 import { filter, switchMap } from 'rxjs/operators';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
 
 @Component({
   selector: 'notifications',
@@ -64,11 +65,13 @@
               private pipelineService: PipelineService,
               public elementIconText: ElementIconText,
               private notificationService: NotificationsService,
-              private notificationCountService: NotificationCountService) {
+              private notificationCountService: NotificationCountService,
+              private breadcrumbService: SpBreadcrumbService) {
     this.unreadNotifications = [];
   }
 
   ngOnInit() {
+    this.breadcrumbService.updateBreadcrumb([{label: 'Notifications'}]);
     this.getPipelinesWithNotifications();
     this.subscription = timer(0, 5000).pipe(
       filter(() => (this.currentlySelectedNotification !== undefined && this.allNotifications.size > 0)),
diff --git a/ui/src/app/pipeline-details/components/actions/pipeline-actions.component.html b/ui/src/app/pipeline-details/components/actions/pipeline-actions.component.html
index 2ee14ea..8bff662 100644
--- a/ui/src/app/pipeline-details/components/actions/pipeline-actions.component.html
+++ b/ui/src/app/pipeline-details/components/actions/pipeline-actions.component.html
@@ -16,58 +16,41 @@
   ~
   -->
 
-<div>
-    <div class="assembly-options-preview sp-blue-bg">
-        <div fxLayout="row" fxLayoutAlign="start center">
-            <h4>Actions</h4>
+<sp-basic-inner-panel panelTitle="Actions">
+    <div fxFlex="100" fxLayoutAlign="center center" fxLayout="row" style="padding:10px">
+        <div fxFlex="30">
+            <button mat-button mat-raised-button color="accent"
+                    matTooltip="Start Pipeline" matTooltipPosition="above"
+                    (click)="startPipeline()"
+                    [disabled]="starting" *ngIf="!pipeline.running">
+                <mat-icon>play_arrow</mat-icon>
+                <span>&nbsp;Start</span>
+            </button>
+            <button mat-button mat-raised-button color="accent"
+                    matTooltip="Stop Pipeline" matTooltipPosition="above"
+                    (click)="stopPipeline()"
+                    [disabled]="stopping" *ngIf="pipeline.running">
+                <mat-icon>stop</mat-icon>
+                <span>&nbsp;Stop</span>
+            </button>
+        </div>
+        <div fxFlex="30">
+            <button mat-button mat-raised-button color="accent"
+                    matTooltip="Modify Pipeline" matTooltipPosition="above"
+                    [disabled]="pipeline.running"
+                    (click)="pipelineOperationsService.modifyPipeline(pipeline._id)">
+                <mat-icon>mode_edit</mat-icon>
+                <span>&nbsp;Modify</span>
+            </button>
+        </div>
+        <div fxFlex="30">
+            <button mat-button mat-raised-button color="accent"
+                    matTooltip="Delete Pipeline" matTooltipPosition="above"
+                    *ngIf="hasPipelineDeletePrivileges"
+                    (click)="pipelineOperationsService.showDeleteDialog(pipeline, reloadPipelineEmitter, this.switchToPipelineView)">
+                <mat-icon>delete</mat-icon>
+                <span>&nbsp;Delete</span>
+            </button>
         </div>
     </div>
-    <div class="sp-blue-border">
-        <div fxFlex="100" fxLayoutAlign="center center" fxLayout="row" style="padding:10px">
-            <div fxFlex="30">
-                <button mat-button mat-raised-button color="accent"
-                        matTooltip="Start Pipeline" matTooltipPosition="above"
-                        (click)="startPipeline()"
-                           [disabled]="starting" *ngIf="!pipeline.running">
-                    <mat-icon>play_arrow</mat-icon>
-                    <span>&nbsp;Start</span>
-                </button>
-                <button mat-button mat-raised-button color="accent"
-                        matTooltip="Stop Pipeline" matTooltipPosition="above"
-                        (click)="stopPipeline()"
-                           [disabled]="stopping" *ngIf="pipeline.running">
-                    <mat-icon>stop</mat-icon>
-                    <span>&nbsp;Stop</span>
-                </button>
-            </div>
-            <div fxFlex="30">
-                <button mat-button mat-raised-button color="accent"
-                        matTooltip="Modify Pipeline" matTooltipPosition="above"
-                        [disabled]="pipeline.running"
-                        (click)="pipelineOperationsService.modifyPipeline(pipeline._id)">
-                    <mat-icon>mode_edit</mat-icon>
-                    <span>&nbsp;Modify</span>
-                </button>
-            </div>
-            <div fxFlex="30">
-                <button mat-button mat-raised-button color="accent"
-                        matTooltip="Delete Pipeline" matTooltipPosition="above"
-                        *ngIf="hasPipelineDeletePrivileges"
-                        (click)="pipelineOperationsService.showDeleteDialog(pipeline, reloadPipelineEmitter, this.switchToPipelineView)">
-                    <mat-icon>delete</mat-icon>
-                    <span>&nbsp;Delete</span>
-                </button>
-            </div>
-<!--            <div flex="30">-->
-<!--            <md-button ng-click="ctrl.PipelineOperationsService.showLogs(ctrl.pipeline._id)" class="md-button">-->
-<!--                <md-icon-->
-<!--                        md-svg-icon="action:ic_info_24px"-->
-<!--                        aria-label="Logs" class="md-accent"></md-icon>-->
-<!--                &nbsp;Logs-->
-<!--                <md-tooltip md-direction="top">-->
-<!--                    Show Logs-->
-<!--                </md-tooltip>-->
-<!--            </md-button>-->
-        </div>
-    </div>
-</div>
+</sp-basic-inner-panel>
diff --git a/ui/src/app/pipeline-details/components/edit/quickedit.component.html b/ui/src/app/pipeline-details/components/edit/quickedit.component.html
index ba52554..c5c44ca 100644
--- a/ui/src/app/pipeline-details/components/edit/quickedit.component.html
+++ b/ui/src/app/pipeline-details/components/edit/quickedit.component.html
@@ -16,43 +16,55 @@
   ~
   -->
 
-<div>
-    <div class="assembly-options-preview sp-blue-bg">
-        <div fxLayout="row" fxLayoutAlign="start center">
-            <h4>Edit configuration</h4>
-            <span fxFlex></span>
-            <button color="accent" mat-button mat-raised-button matTooltip="Save Pipeline" matTooltipPosition="above"
-                    style="display:flex;align-items:center;" class="settings-bar-icon-button"
-                    [disabled]="(!formValid || pipelineUpdating)"
-                    (click)="updatePipeline()">
-                <mat-icon>save</mat-icon>
-                <span>&nbsp;Update pipeline</span>
-            </button>
-        </div>
-    </div>
-    <div class="sp-blue-border">
-        <div *ngIf="selectedElement">
-            <div fxLayout="column" style="padding:5px;padding-left:10px;">
-                <pipeline-elements-row [pipeline]="pipeline"
-                                       [element]="selectedElement"></pipeline-elements-row>
+<sp-basic-nav-tabs [spNavigationItems]="tabs"
+                   [activeLink]="'quick-edit'"
+                   [showBackLink]="true"
+                   [backLinkTarget]="['pipelines']">
 
-                <div fxFlex="100" fxLayout="column"
-                     *ngIf="isInvocable">
-                        <form [formGroup]="parentForm" fxFlex="100">
-                            <app-static-property *ngFor="let config of _selectedElement.staticProperties"
-                                                 [staticProperty]="config"
-                                                 [displayRecommended]="true"
-                                                 [staticProperties]="_selectedElement.staticProperties"
-                                                 [eventSchemas]="eventSchemas"
-                                                 [parentForm]="parentForm"
-                                                 [fieldName]="config.internalName">
-                            </app-static-property>
-                        </form>
+    <div fxLayout="column" class="page-container-padding" *ngIf="pipeline">
+        <pipeline-preview [jspcanvas]="'assembly-preview'"
+                          [pipeline]="pipeline"
+                          (selectedElementEmitter)="selectElement($event)"
+                          style="margin-bottom:15px;"
+                          class="md-padding"
+                          *ngIf="pipelineAvailable"></pipeline-preview>
+
+        <sp-basic-inner-panel panelTitle="Edit Configuration">
+            <div header fxLayoutAlign="end center" fxFlex="100" fxLayout="row">
+                <button color="accent" mat-button mat-raised-button matTooltip="Save Pipeline"
+                        matTooltipPosition="above"
+                        style="display:flex;align-items:center;" class="settings-bar-icon-button"
+                        [disabled]="(!formValid || pipelineUpdating)"
+                        (click)="updatePipeline()">
+                    <mat-icon>save</mat-icon>
+                    <span>&nbsp;Update pipeline</span>
+                </button>
+            </div>
+            <div fxFlex="100" fxLayout="column">
+                <div *ngIf="selectedElement">
+                    <div fxLayout="column" style="padding:5px;padding-left:10px;">
+                        <pipeline-elements-row [pipeline]="pipeline"
+                                               [element]="selectedElement"></pipeline-elements-row>
+
+                        <div fxFlex="100" fxLayout="column"
+                             *ngIf="isInvocable">
+                            <form [formGroup]="parentForm" fxFlex="100">
+                                <app-static-property *ngFor="let config of _selectedElement.staticProperties"
+                                                     [staticProperty]="config"
+                                                     [displayRecommended]="true"
+                                                     [staticProperties]="_selectedElement.staticProperties"
+                                                     [eventSchemas]="eventSchemas"
+                                                     [parentForm]="parentForm"
+                                                     [fieldName]="config.internalName">
+                                </app-static-property>
+                            </form>
+                        </div>
+                    </div>
+                </div>
+                <div fxLayout="column" fxLayoutAlign="center center" *ngIf="!selectedElement">
+                    (select an element in the preview window to modify it)
                 </div>
             </div>
-        </div>
-        <div fxLayout="column" fxLayoutAlign="center center" *ngIf="!selectedElement">
-            (select an element in the preview window to modify it)
-        </div>
+        </sp-basic-inner-panel>
     </div>
-</div>
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/pipeline-details/components/edit/quickedit.component.ts b/ui/src/app/pipeline-details/components/edit/quickedit.component.ts
index 15877ec..5432ce0 100644
--- a/ui/src/app/pipeline-details/components/edit/quickedit.component.ts
+++ b/ui/src/app/pipeline-details/components/edit/quickedit.component.ts
@@ -16,135 +16,136 @@
  *
  */
 
+import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
 import {
-    AfterViewInit,
-    ChangeDetectorRef,
-    Component,
-    EventEmitter,
-    Input,
-    OnInit,
-    Output
-} from '@angular/core';
-import {
-    PipelineService,
-    DataProcessorInvocation,
-    DataSinkInvocation,
-    EventSchema,
-    Pipeline
+  DataProcessorInvocation,
+  DataSinkInvocation,
+  EventSchema,
+  PipelineService
 } from '@streampipes/platform-services';
 import { PipelineElementUnion } from '../../../editor/model/editor.model';
 import { FormBuilder, FormGroup } from '@angular/forms';
+import { SpPipelineDetailsDirective } from '../sp-pipeline-details.directive';
+import { ActivatedRoute } from '@angular/router';
+import { AuthService } from '../../../services/auth.service';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpPipelineRoutes } from '../../../pipelines/pipelines.routes';
 
 @Component({
-    selector: 'quick-edit',
-    templateUrl: './quickedit.component.html',
+  selector: 'quick-edit',
+  templateUrl: './quickedit.component.html',
 })
-export class QuickEditComponent implements OnInit, AfterViewInit {
+export class QuickEditComponent extends SpPipelineDetailsDirective implements OnInit, AfterViewInit {
 
-    @Input()
-    pipeline: Pipeline;
+  _selectedElement: PipelineElementUnion;
 
-    @Output()
-    reloadPipelineEmitter: EventEmitter<void> = new EventEmitter<void>();
+  eventSchemas: EventSchema[];
 
-    _selectedElement: PipelineElementUnion;
+  parentForm: FormGroup;
+  formValid: boolean;
+  viewInitialized = false;
 
-    eventSchemas: EventSchema[];
+  isInvocable = false;
+  isDataProcessor = false;
 
-    parentForm: FormGroup;
-    formValid: boolean;
-    viewInitialized = false;
+  pipelineUpdating = false;
 
-    isInvocable = false;
-    isDataProcessor = false;
+  constructor(activatedRoute: ActivatedRoute,
+              pipelineService: PipelineService,
+              authService: AuthService,
+              private fb: FormBuilder,
+              private changeDetectorRef: ChangeDetectorRef,
+              breadcrumbService: SpBreadcrumbService) {
+    super(activatedRoute, pipelineService, authService, breadcrumbService);
+  }
 
-    pipelineUpdating = false;
+  ngOnInit() {
+    super.onInit();
+    this.parentForm = this.fb.group({});
 
-    constructor(private pipelineService: PipelineService,
-                private fb: FormBuilder,
-                private changeDetectorRef: ChangeDetectorRef) {
+    this.parentForm.statusChanges.subscribe((status) => {
+      this.formValid = this.viewInitialized && this.parentForm.valid;
+    });
+  }
 
+  ngAfterViewInit(): void {
+    this.viewInitialized = true;
+    this.formValid = this.viewInitialized && this.parentForm.valid;
+    this.changeDetectorRef.detectChanges();
+  }
+
+  updatePipeline() {
+    this.pipelineUpdating = true;
+    this.updatePipelineElement();
+    this.pipelineService.updatePipeline(this.pipeline).subscribe(data => {
+      this.loadPipeline();
+      this.pipelineUpdating = false;
+    });
+  }
+
+  updatePipelineElement() {
+    if (this._selectedElement instanceof DataProcessorInvocation) {
+      this.updateDataProcessor();
+    } else if (this._selectedElement instanceof DataSinkInvocation) {
+      this.updateDataSink();
     }
+  }
 
-    ngOnInit() {
-        this.parentForm = this.fb.group({
-        });
+  updateDataProcessor() {
+    const dataProcessors: DataProcessorInvocation[] = [];
+    this.pipeline.sepas.forEach(p => {
+      if (p.dom === this._selectedElement.dom) {
+        dataProcessors.push(this._selectedElement as DataProcessorInvocation);
+      } else {
+        dataProcessors.push(p);
+      }
+    });
+    this.pipeline.sepas = dataProcessors;
+  }
 
-        this.parentForm.statusChanges.subscribe((status) => {
-            this.formValid = this.viewInitialized && this.parentForm.valid;
-        });
+  updateDataSink() {
+    const dataSinks: DataSinkInvocation[] = [];
+    this.pipeline.actions.forEach(p => {
+      if (p.dom === this._selectedElement.dom) {
+        dataSinks.push(this._selectedElement as DataSinkInvocation);
+      } else {
+        dataSinks.push(p);
+      }
+    });
+    this.pipeline.actions = dataSinks;
+  }
+
+  get selectedElement() {
+    return this._selectedElement;
+  }
+
+  @Input()
+  set selectedElement(selectedElement: PipelineElementUnion) {
+    if (this._selectedElement) {
+      this.updatePipelineElement();
     }
-
-    ngAfterViewInit(): void {
-        this.viewInitialized = true;
-        this.formValid = this.viewInitialized && this.parentForm.valid;
-        this.changeDetectorRef.detectChanges();
+    this._selectedElement = selectedElement;
+    this.eventSchemas = [];
+    if (this._selectedElement instanceof DataProcessorInvocation || this._selectedElement instanceof DataSinkInvocation) {
+      (this._selectedElement as any).inputStreams.forEach(is => {
+        this.eventSchemas = this.eventSchemas.concat(is.eventSchema);
+      });
     }
+    this.updateTypeInfo();
+  }
 
-    updatePipeline() {
-        this.pipelineUpdating = true;
-        this.updatePipelineElement();
-        this.pipelineService.updatePipeline(this.pipeline).subscribe(data => {
-            this.reloadPipelineEmitter.emit();
-            this.pipelineUpdating = false;
-        });
-    }
+  updateTypeInfo() {
+    this.isDataProcessor = this._selectedElement instanceof DataProcessorInvocation;
+    this.isInvocable = this._selectedElement instanceof DataProcessorInvocation ||
+      this._selectedElement instanceof DataSinkInvocation;
+  }
 
-    updatePipelineElement() {
-        if (this._selectedElement instanceof DataProcessorInvocation) {
-            this.updateDataProcessor();
-        } else if (this._selectedElement instanceof DataSinkInvocation) {
-            this.updateDataSink();
-        }
-    }
+  selectElement(element: PipelineElementUnion) {
+    this.selectedElement = element;
+  }
 
-    updateDataProcessor() {
-        const dataProcessors: DataProcessorInvocation[] = [];
-        this.pipeline.sepas.forEach(p => {
-           if (p.dom === this._selectedElement.dom) {
-               dataProcessors.push(this._selectedElement as DataProcessorInvocation);
-           } else {
-                dataProcessors.push(p);
-           }
-        });
-        this.pipeline.sepas = dataProcessors;
-    }
-
-    updateDataSink() {
-        const dataSinks: DataSinkInvocation[] = [];
-        this.pipeline.actions.forEach(p => {
-            if (p.dom === this._selectedElement.dom) {
-                dataSinks.push(this._selectedElement as DataSinkInvocation);
-            } else {
-                dataSinks.push(p);
-            }
-        });
-        this.pipeline.actions = dataSinks;
-    }
-
-    get selectedElement() {
-        return this._selectedElement;
-    }
-
-    @Input()
-    set selectedElement(selectedElement: PipelineElementUnion) {
-        if (this._selectedElement) {
-            this.updatePipelineElement();
-        }
-        this._selectedElement = selectedElement;
-        this.eventSchemas = [];
-        if (this._selectedElement instanceof DataProcessorInvocation || this._selectedElement instanceof DataSinkInvocation) {
-            (this._selectedElement as any).inputStreams.forEach(is => {
-                this.eventSchemas = this.eventSchemas.concat(is.eventSchema);
-            });
-        }
-        this.updateTypeInfo();
-    }
-
-    updateTypeInfo() {
-        this.isDataProcessor = this._selectedElement instanceof DataProcessorInvocation;
-        this.isInvocable = this._selectedElement instanceof DataProcessorInvocation ||
-            this._selectedElement instanceof DataSinkInvocation;
-    }
+  onPipelineAvailable(): void {
+    this.breadcrumbService.updateBreadcrumb([SpPipelineRoutes.BASE, {label: this.pipeline.name}, {label: 'Quick Edit'} ]);
+  }
 }
 
diff --git a/ui/src/app/pipeline-details/components/elements/pipeline-elements.component.html b/ui/src/app/pipeline-details/components/elements/pipeline-elements.component.html
index 4af2449..c046264 100644
--- a/ui/src/app/pipeline-details/components/elements/pipeline-elements.component.html
+++ b/ui/src/app/pipeline-details/components/elements/pipeline-elements.component.html
@@ -16,13 +16,9 @@
   ~
   -->
 
-<div>
-    <div class="assembly-options-preview sp-blue-bg">
-        <div fxLayout="row" fxLayoutAlign="start center">
-            <h4>Element Details</h4>
-        </div>
-    </div>
-    <div class="sp-blue-border" style="max-height: 800px;overflow:auto;">
+<sp-basic-inner-panel panelTitle="Element Details">
+
+    <div style="max-height: 800px;overflow:auto;">
         <div *ngIf="selectedElement">
             <div fxLayout="column" style="padding:5px;padding-left:10px;">
                 <pipeline-elements-row [pipeline]="pipeline" [element]="selectedElement"></pipeline-elements-row>
@@ -36,4 +32,4 @@
             (select an element in the preview window to see details)
         </div>
     </div>
-</div>
\ No newline at end of file
+</sp-basic-inner-panel>
diff --git a/ui/src/app/pipeline-details/components/monitoring/pipeline-monitoring.component.html b/ui/src/app/pipeline-details/components/monitoring/pipeline-monitoring.component.html
index 4c27a46..3f4b4c1 100644
--- a/ui/src/app/pipeline-details/components/monitoring/pipeline-monitoring.component.html
+++ b/ui/src/app/pipeline-details/components/monitoring/pipeline-monitoring.component.html
@@ -16,51 +16,52 @@
   ~
   -->
 
+<sp-basic-nav-tabs [spNavigationItems]="tabs"
+                   [activeLink]="'monitoring'"
+                   [showBackLink]="true"
+                   [backLinkTarget]="['pipelines']">
 
-<div fxFlex="100" fxLayout="column">
-    <div fxLayout="column" class="fixed-height add-options">
-        <div class="add-options-item" fxLayoutAlign="start center" fxLayout="row" style="padding-right:10px;">
-            <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
-                <mat-slide-toggle [(ngModel)]="autoRefresh" color="accent">Auto refresh</mat-slide-toggle>
-            </div>
-        </div>
+    <div nav fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
+        <mat-slide-toggle [(ngModel)]="autoRefresh" color="accent">Auto refresh</mat-slide-toggle>
     </div>
-    <div fxFlex="100" fxLayout="column" class="page-container-padding-inner">
-        <div fxFlex="100" *ngIf="!pipeline.running" fxLayout="column" fxLayoutAlign="center center">
-            <div class="error-message">(monitoring info is only available for running pipelines)</div>
-            <button mat-button mat-raised-button color="accent"
-                    matTooltip="Start Pipeline" matTooltipPosition="above"
-                    *ngIf="hasPipelineWritePrivileges"
-                    (click)="startPipeline()">
-                <mat-icon>play_arrow</mat-icon>
-                <span>&nbsp;Start pipeline</span>
-            </button>
-        </div>
-        <div fxFlex="100" *ngIf="pipeline.running && pipelineMonitoringInfoAvailable">
-            <div *ngFor="let pipelineElement of allElements" fxLayout="column" class="mb-10">
-                <div class="assembly-options-preview sp-blue-bg" [id]="pipelineElement.elementId">
-                    <div fxLayout="row" fxLayoutAlign="start center">
-                        <h4>{{pipelineElement.name}}</h4>
-                    </div>
-                </div>
-                <div class="sp-blue-border pipeline-element-statistics-panel">
-                    <div fxFlex="100" fxLayout="row">
-                        <div fxFlex="20" fxLayoutAlign="start start">
-                            <pipeline-elements-row style="width: 100%;"
-                                                   [showDescription]="false"
-                                                   [pipeline]="pipeline"
-                                                   [element]="pipelineElement"></pipeline-elements-row>
+    <div fxLayout="column" class="page-container-padding" *ngIf="pipeline">
+        <div fxFlex="100" fxLayout="column" class="page-container-padding-inner">
+            <div fxFlex="100" *ngIf="!pipeline.running" fxLayout="column" fxLayoutAlign="center center">
+                <div class="error-message">(monitoring info is only available for running pipelines)</div>
+                <button mat-button mat-raised-button color="accent"
+                        matTooltip="Start Pipeline" matTooltipPosition="above"
+                        *ngIf="hasPipelineWritePrivileges"
+                        (click)="startPipeline()">
+                    <mat-icon>play_arrow</mat-icon>
+                    <span>&nbsp;Start pipeline</span>
+                </button>
+            </div>
+            <div fxFlex="100" *ngIf="pipeline.running && pipelineMonitoringInfoAvailable">
+                <div *ngFor="let pipelineElement of allElements" fxLayout="column" class="mb-10">
+                    <div class="assembly-options-preview sp-blue-bg" [id]="pipelineElement.elementId">
+                        <div fxLayout="row" fxLayoutAlign="start center">
+                            <h4>{{pipelineElement.name}}</h4>
                         </div>
-                        <div fxFlex="80" fxLayoutAlign="start center">
-                            <pipeline-element-statistics
-                                    [pipeline]="pipeline"
-                                    [pipelineElement]="pipelineElement"
-                                    [pipelineElementMonitoringInfo]="pipelineElementMonitoringInfo.get(pipelineElement.elementId)">
-                            </pipeline-element-statistics>
+                    </div>
+                    <div class="sp-blue-border pipeline-element-statistics-panel">
+                        <div fxFlex="100" fxLayout="row">
+                            <div fxFlex="20" fxLayoutAlign="start start">
+                                <pipeline-elements-row style="width: 100%;"
+                                                       [showDescription]="false"
+                                                       [pipeline]="pipeline"
+                                                       [element]="pipelineElement"></pipeline-elements-row>
+                            </div>
+                            <div fxFlex="80" fxLayoutAlign="start center">
+                                <pipeline-element-statistics
+                                        [pipeline]="pipeline"
+                                        [pipelineElement]="pipelineElement"
+                                        [pipelineElementMonitoringInfo]="pipelineElementMonitoringInfo.get(pipelineElement.elementId)">
+                                </pipeline-element-statistics>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
         </div>
     </div>
-</div>
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/pipeline-details/components/monitoring/pipeline-monitoring.component.ts b/ui/src/app/pipeline-details/components/monitoring/pipeline-monitoring.component.ts
index ea83eda..0641963 100644
--- a/ui/src/app/pipeline-details/components/monitoring/pipeline-monitoring.component.ts
+++ b/ui/src/app/pipeline-details/components/monitoring/pipeline-monitoring.component.ts
@@ -16,29 +16,31 @@
  *
  */
 
-import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
+import { Component, EventEmitter, OnDestroy, OnInit } from '@angular/core';
 import {
-  DataProcessorInvocation, DataSinkInvocation,
-  Pipeline, PipelineElementMonitoringInfo,
+  DataProcessorInvocation,
+  DataSinkInvocation,
+  PipelineElementMonitoringInfo,
   PipelineMonitoringInfo,
-  SpDataSet, SpDataStream
+  PipelineMonitoringService,
+  PipelineService,
+  SpDataSet,
+  SpDataStream
 } from '@streampipes/platform-services';
-import { PipelineMonitoringService } from '@streampipes/platform-services';
 import { PipelineOperationsService } from '../../../pipelines/services/pipeline-operations.service';
 import { AuthService } from '../../../services/auth.service';
-import { UserPrivilege } from '../../../_enums/user-privilege.enum';
+import { SpPipelineDetailsDirective } from '../sp-pipeline-details.directive';
+import { ActivatedRoute } from '@angular/router';
+import { Subscription } from 'rxjs';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpPipelineRoutes } from '../../../pipelines/pipelines.routes';
 
 @Component({
   selector: 'pipeline-monitoring',
   templateUrl: './pipeline-monitoring.component.html',
   styleUrls: ['./pipeline-monitoring.component.scss']
 })
-export class PipelineMonitoringComponent implements OnInit, OnDestroy {
-
-  _pipeline: Pipeline;
-
-  @Output()
-  reloadPipelineEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
+export class PipelineMonitoringComponent extends SpPipelineDetailsDirective implements OnInit, OnDestroy {
 
   pipelineMonitoringInfo: PipelineMonitoringInfo;
   pipelineMonitoringInfoAvailable = false;
@@ -49,19 +51,21 @@
 
   pipelineElementMonitoringInfo: Map<string, PipelineElementMonitoringInfo>;
 
-  hasPipelineWritePrivileges = false;
+  reloadPipelinesEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
+  reloadSubscription: Subscription;
 
-  constructor(private pipelineMonitoringService: PipelineMonitoringService,
+  constructor(activatedRoute: ActivatedRoute,
+              pipelineService: PipelineService,
+              authService: AuthService,
+              private pipelineMonitoringService: PipelineMonitoringService,
               private pipelineOperationsService: PipelineOperationsService,
-              private authService: AuthService) {
+              breadcrumbService: SpBreadcrumbService) {
+    super(activatedRoute, pipelineService, authService, breadcrumbService);
   }
 
   ngOnInit(): void {
-    this.authService.user$.subscribe(user => {
-      this.hasPipelineWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_PIPELINE);
-    });
-    this.collectAllElements();
-    this.checkMonitoringInfoCollection();
+    super.onInit();
+    this.reloadSubscription = this.reloadPipelinesEmitter.subscribe(reload => this.loadPipeline());
   }
 
   checkMonitoringInfoCollection() {
@@ -101,20 +105,17 @@
 
   ngOnDestroy(): void {
     this.autoRefresh = false;
+    this.reloadSubscription.unsubscribe();
   }
 
   startPipeline() {
-    this.pipelineOperationsService.startPipeline(this.pipeline._id, this.reloadPipelineEmitter);
+    this.pipelineOperationsService.startPipeline(this.pipeline._id, this.reloadPipelinesEmitter);
   }
 
-  @Input()
-  set pipeline(pipeline: Pipeline) {
-    this._pipeline = pipeline;
+  onPipelineAvailable(): void {
+    this.breadcrumbService.updateBreadcrumb([SpPipelineRoutes.BASE, {label: this.pipeline.name}, {label: 'Monitoring'} ]);
+    this.collectAllElements();
     this.checkMonitoringInfoCollection();
   }
 
-  get pipeline() {
-    return this._pipeline;
-  }
-
 }
diff --git a/ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.html b/ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.html
new file mode 100644
index 0000000..eca67ef
--- /dev/null
+++ b/ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.html
@@ -0,0 +1,46 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<sp-basic-nav-tabs [spNavigationItems]="tabs" [activeLink]="'overview'" [showBackLink]="true" [backLinkTarget]="['pipelines']">
+    <div fxLayout="column" class="page-container-padding">
+        <div fxFlex="100" fxLayout="column">
+            <pipeline-preview [jspcanvas]="'assembly-preview'"
+                              [pipeline]="pipeline"
+                              (selectedElementEmitter)="selectElement($event)"
+                              style="margin-bottom:15px;"
+                              class="md-padding"
+                              *ngIf="pipelineAvailable"></pipeline-preview>
+            <div fxFlex fxLayout="row" fxLayoutAlign="start top" *ngIf="pipelineAvailable">
+                <div fxFlex="60" class="md-padding">
+                    <div fxFlex fxLayout="column">
+                        <pipeline-elements [pipeline]="pipeline"
+                                           [selectedElement]="selectedElement"></pipeline-elements>
+                    </div>
+                </div>
+                <div fxFlex="40" class="md-padding">
+                    <div fxFlex fxLayout="column">
+                        <pipeline-actions (reloadPipelineEmitter)="loadPipeline()" [pipeline]="pipeline"
+                                          style="margin-bottom:15px;"
+                                          *ngIf="hasPipelineWritePrivileges"></pipeline-actions>
+                        <pipeline-status [pipeline]="pipeline"></pipeline-status>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</sp-basic-nav-tabs>
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.scss
similarity index 99%
rename from ui/src/app/pipeline-details/pipeline-details.component.scss
rename to ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.scss
index a375af7..1100ab4 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.scss
@@ -19,4 +19,3 @@
 .md-padding {
   padding: 10px;
 }
-
diff --git a/ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.ts b/ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.ts
new file mode 100644
index 0000000..edc0d6a
--- /dev/null
+++ b/ui/src/app/pipeline-details/components/overview/pipeline-details-overview.component.ts
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { SpPipelineDetailsDirective } from '../sp-pipeline-details.directive';
+import { AuthService } from '../../../services/auth.service';
+import { PipelineService } from '@streampipes/platform-services';
+import { PipelineElementUnion } from '../../../editor/model/editor.model';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpPipelineRoutes } from '../../../pipelines/pipelines.routes';
+
+@Component({
+  selector: 'sp-pipeline-details-overview-component',
+  templateUrl: './pipeline-details-overview.component.html',
+  styleUrls: ['./pipeline-details-overview.component.scss']
+})
+export class SpPipelineDetailsOverviewComponent extends SpPipelineDetailsDirective implements OnInit {
+
+  tabs = [];
+  selectedElement: PipelineElementUnion;
+
+  constructor(activatedRoute: ActivatedRoute,
+              pipelineService: PipelineService,
+              authService: AuthService,
+              breadcrumbService: SpBreadcrumbService) {
+    super(activatedRoute, pipelineService, authService, breadcrumbService);
+  }
+
+  ngOnInit(): void {
+    super.onInit();
+  }
+
+  selectElement(element: PipelineElementUnion) {
+    this.selectedElement = element;
+  }
+
+  onPipelineAvailable(): void {
+    this.breadcrumbService.updateBreadcrumb([SpPipelineRoutes.BASE, {label: this.pipeline.name}, {label: 'Overview'} ]);
+  }
+
+
+}
diff --git a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
index 93e8f4f..f9a1188 100644
--- a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
+++ b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
@@ -16,15 +16,12 @@
   ~
   -->
 
-<div class="assembly-options-preview sp-blue-bg">
-    <div fxLayout="row" fxLayoutAlign="start center">
-        <h4>Preview: {{pipeline.name}}</h4>
-    </div>
-</div>
-<div class="outer-assembly-preview">
-    <div class="canvas-preview-inner">
-        <div id="{{jspcanvas}}" class="canvas-preview">
-            <pipeline [canvasId]="jspcanvas" [rawPipelineModel]="rawPipelineModel" [preview]="true"></pipeline>
+<sp-basic-inner-panel [panelTitle]="'Preview: ' +pipeline.name" innerPadding="0">
+    <div class="outer-assembly-preview">
+        <div class="canvas-preview-inner">
+            <div id="{{jspcanvas}}" class="canvas-preview">
+                <pipeline [canvasId]="jspcanvas" [rawPipelineModel]="rawPipelineModel" [preview]="true"></pipeline>
+            </div>
         </div>
     </div>
-</div>
+</sp-basic-inner-panel>
diff --git a/ui/src/app/pipeline-details/components/sp-pipeline-details.directive.ts b/ui/src/app/pipeline-details/components/sp-pipeline-details.directive.ts
new file mode 100644
index 0000000..68712a9
--- /dev/null
+++ b/ui/src/app/pipeline-details/components/sp-pipeline-details.directive.ts
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Directive } from '@angular/core';
+import { UserPrivilege } from '../../_enums/user-privilege.enum';
+import { ActivatedRoute } from '@angular/router';
+import { AuthService } from '../../services/auth.service';
+import { Pipeline, PipelineService } from '@streampipes/platform-services';
+import { SpPipelineDetailsTabs } from '../pipeline-details-tabs';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+
+@Directive()
+export abstract class SpPipelineDetailsDirective {
+
+  tabs = [];
+  hasPipelineWritePrivileges = false;
+  hasPipelineDeletePrivileges = false;
+
+  currentPipeline: string;
+  pipeline: Pipeline;
+  pipelineAvailable = false;
+
+  constructor(protected activatedRoute: ActivatedRoute,
+              protected pipelineService: PipelineService,
+              protected authService: AuthService,
+              protected breadcrumbService: SpBreadcrumbService) {
+  }
+
+  onInit(): void {
+    this.authService.user$.subscribe(user => {
+      this.hasPipelineWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_PIPELINE);
+      this.hasPipelineDeletePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_DELETE_PIPELINE);
+      const pipelineId = this.activatedRoute.snapshot.params.pipelineId;
+      if (pipelineId) {
+        this.tabs = new SpPipelineDetailsTabs().getTabs(pipelineId);
+        this.currentPipeline = pipelineId;
+        this.loadPipeline();
+      }
+    });
+  }
+
+  loadPipeline(): void {
+    this.pipelineService.getPipelineById(this.currentPipeline)
+      .subscribe(pipeline => {
+        this.pipeline = pipeline;
+        this.pipelineAvailable = true;
+        this.onPipelineAvailable();
+      });
+  }
+
+  abstract onPipelineAvailable(): void;
+
+}
diff --git a/ui/src/app/pipeline-details/components/status/pipeline-status.component.html b/ui/src/app/pipeline-details/components/status/pipeline-status.component.html
index 5083595e..813b376 100644
--- a/ui/src/app/pipeline-details/components/status/pipeline-status.component.html
+++ b/ui/src/app/pipeline-details/components/status/pipeline-status.component.html
@@ -16,12 +16,7 @@
   ~
   -->
 
-<div class="assembly-options-preview sp-blue-bg">
-    <div fxLayout="row" fxLayoutAlign="start center">
-        <h4>Pipeline Status</h4>
-    </div>
-</div>
-<div class="sp-blue-border">
+<sp-basic-inner-panel panelTitle="Pipeline Status">
     <div fxLayout="column" style="min-height:100px; padding:5px;padding-left:15px;" *ngIf="pipelineStatus.length > 0">
         <div fxLayout="row" fxFlex="100">
             <div fxFlex="20"><h5><b>Date</b></h5></div>
@@ -41,4 +36,4 @@
     <div fxLayout="column"fxLayoutAlign="center center" style="min-height:100px; padding:5px;padding-left:15px;" *ngIf="pipelineStatus.length==0">
         (no status information available)
     </div>
-</div>
\ No newline at end of file
+</sp-basic-inner-panel>
diff --git a/ui/src/app/pipeline-details/pipeline-details-tabs.ts b/ui/src/app/pipeline-details/pipeline-details-tabs.ts
new file mode 100644
index 0000000..966c4a7
--- /dev/null
+++ b/ui/src/app/pipeline-details/pipeline-details-tabs.ts
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { SpNavigationItem } from '@streampipes/shared-ui';
+
+export class SpPipelineDetailsTabs {
+
+  public getTabs(pipelineId: string): SpNavigationItem[] {
+    return [
+      {itemId: 'overview', itemTitle: 'Overview', itemLink: ['pipelines', 'details', pipelineId, 'overview']},
+      {itemId: 'monitoring', itemTitle: 'Monitoring', itemLink: ['pipelines', 'details', pipelineId, 'monitoring']},
+      // {itemId: 'errors', itemTitle: 'Errors', itemLink: ['pipelines', 'details', pipelineId, 'errors']},
+      {itemId: 'quick-edit', itemTitle: 'Quick Edit', itemLink: ['pipelines', 'details', pipelineId, 'quick-edit']}
+    ];
+  }
+}
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.html b/ui/src/app/pipeline-details/pipeline-details.component.html
deleted file mode 100644
index 2733ce1..0000000
--- a/ui/src/app/pipeline-details/pipeline-details.component.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div fxLayout="column" class="page-container">
-    <div fxLayout="row" class="border sp-tab-bg" style="padding:0px">
-        <div fxFlex="100" class="page-container-nav">
-            <div fxFlex="100" fxLayout="row">
-                <mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="setSelectedIndex($event)" color="accent">
-                    <mat-tab label="Overview"></mat-tab>
-                    <mat-tab label="Monitoring"></mat-tab>
-                    <mat-tab label="Errors"></mat-tab>
-                    <mat-tab label="Quick Edit" [disabled]="pipelineAvailable && pipeline.running" *ngIf="hasPipelineWritePrivileges"></mat-tab>
-                </mat-tab-group>
-            </div>
-        </div>
-    </div>
-    <div fxFlex="100" fxLayout="column">
-        <pipeline-preview [jspcanvas]="'assembly-preview'"
-                          [pipeline]="pipeline"
-                          (selectedElementEmitter)="selectElement($event)"
-                          style="margin-bottom:15px;"
-                          class="md-padding"
-                          *ngIf="pipelineAvailable"></pipeline-preview>
-    <div fxFlex fxLayout="row" fxLayoutAlign="start top" *ngIf="pipelineAvailable && selectedIndex == 0">
-        <div fxFlex="60" class="md-padding">
-            <div fxFlex fxLayout="column">
-                <pipeline-elements [pipeline]="pipeline"
-                                   [selectedElement]="selectedElement"></pipeline-elements>
-            </div>
-        </div>
-        <div fxFlex="40" class="md-padding">
-            <div fxFlex fxLayout="column">
-                <pipeline-actions (reloadPipelineEmitter)="loadPipeline()" [pipeline]="pipeline"
-                                  style="margin-bottom:15px;" *ngIf="hasPipelineWritePrivileges"></pipeline-actions>
-                <pipeline-status [pipeline]="pipeline"></pipeline-status>
-            </div>
-        </div>
-    </div>
-    <div fxFlex fxLayout="column" fxLayoutAlign="start top" *ngIf="pipelineAvailable && selectedIndex == 1">
-        <pipeline-monitoring [pipeline]="pipeline" (reloadPipelineEmitter)="loadPipeline()"></pipeline-monitoring>
-    </div>
-    <div fxFlex fxLayout="row" fxLayoutAlign="start top" *ngIf="pipelineAvailable && selectedIndex == 3">
-        <div fxFlex="100" class="md-padding">
-            <div fxFlex fxLayout="column">
-                <quick-edit [pipeline]="pipeline" [selectedElement]="selectedElement" (reloadPipelineEmitter)="loadPipeline()"></quick-edit>
-            </div>
-        </div>
-    </div>
-    </div>
-</div>
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.ts b/ui/src/app/pipeline-details/pipeline-details.component.ts
deleted file mode 100644
index 9350874..0000000
--- a/ui/src/app/pipeline-details/pipeline-details.component.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Component, OnInit } from '@angular/core';
-import { Pipeline, PipelineService } from '@streampipes/platform-services';
-import { PipelineElementUnion } from '../editor/model/editor.model';
-import { ActivatedRoute } from '@angular/router';
-import { AuthService } from '../services/auth.service';
-import { UserPrivilege } from '../_enums/user-privilege.enum';
-
-@Component({
-    selector: 'pipeline-details',
-    templateUrl: './pipeline-details.component.html',
-    styleUrls: ['./pipeline-details.component.scss']
-})
-export class PipelineDetailsComponent implements OnInit {
-
-    currentPipeline: string;
-    pipeline: Pipeline;
-    pipelineAvailable = false;
-
-    selectedIndex = 0;
-    selectedElement: PipelineElementUnion;
-
-    hasPipelineWritePrivileges = false;
-    hasPipelineDeletePrivileges = false;
-
-    constructor(private activatedRoute: ActivatedRoute,
-                private pipelineService: PipelineService,
-                private authService: AuthService) {
-    }
-
-    ngOnInit() {
-        this.authService.user$.subscribe(user => {
-            this.hasPipelineWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_PIPELINE);
-            this.hasPipelineDeletePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_DELETE_PIPELINE);
-        });
-        this.activatedRoute.queryParams.subscribe(params => {
-            if (params['pipeline']) {
-                this.currentPipeline = params['pipeline'];
-                this.loadPipeline();
-            }
-        });
-    }
-
-    setSelectedIndex(index: number) {
-        this.selectedIndex = index;
-    }
-
-    loadPipeline() {
-        this.pipelineService.getPipelineById(this.currentPipeline)
-            .subscribe(pipeline => {
-                this.pipeline = pipeline;
-                this.pipelineAvailable = true;
-            });
-    }
-
-    selectElement(element: PipelineElementUnion) {
-        this.selectedElement = element;
-    }
-
-}
diff --git a/ui/src/app/pipeline-details/pipeline-details.module.ts b/ui/src/app/pipeline-details/pipeline-details.module.ts
index 8978f7d..7afc3a8 100644
--- a/ui/src/app/pipeline-details/pipeline-details.module.ts
+++ b/ui/src/app/pipeline-details/pipeline-details.module.ts
@@ -24,7 +24,6 @@
 import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
 import { CommonModule } from '@angular/common';
 import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { PipelineDetailsComponent } from './pipeline-details.component';
 import { PipelinePreviewComponent } from './components/preview/pipeline-preview.component';
 import { EditorModule } from '../editor/editor.module';
 import { PipelineActionsComponent } from './components/actions/pipeline-actions.component';
@@ -39,40 +38,42 @@
 import { BarchartWidgetComponent } from './components/monitoring/widget/barchart/barchart-widget.component';
 import { StatusWidgetComponent } from './components/monitoring/widget/status/status-widget.component';
 import { PlatformServicesModule } from '@streampipes/platform-services';
+import { SpPipelineDetailsOverviewComponent } from './components/overview/pipeline-details-overview.component';
+import { SharedUiModule } from '@streampipes/shared-ui';
 
 @NgModule({
-    imports: [
-        CoreUiModule,
-        FlexLayoutModule,
-        FormsModule,
-        MatTabsModule,
-        MatButtonModule,
-        CustomMaterialModule,
-        CommonModule,
-        MatProgressSpinnerModule,
-        NgxChartsModule,
-        EditorModule,
-        FormsModule,
-        ReactiveFormsModule,
-        PlatformServicesModule
-    ],
-    declarations: [
-        PipelineActionsComponent,
-        PipelineElementsComponent,
-        PipelineElementsRowComponent,
-        PipelineElementStatisticsComponent,
-        PipelineDetailsComponent,
-        PipelineMonitoringComponent,
-        PipelineStatusComponent,
-        PipelinePreviewComponent,
-        QuickEditComponent,
-        StatusWidgetComponent,
-        BarchartWidgetComponent
-    ],
-    providers: [],
-    exports: [
-        PipelineDetailsComponent
-    ]
+  imports: [
+    CoreUiModule,
+    FlexLayoutModule,
+    FormsModule,
+    MatTabsModule,
+    MatButtonModule,
+    CustomMaterialModule,
+    CommonModule,
+    MatProgressSpinnerModule,
+    NgxChartsModule,
+    EditorModule,
+    FormsModule,
+    ReactiveFormsModule,
+    PlatformServicesModule,
+    SharedUiModule
+  ],
+  declarations: [
+    PipelineActionsComponent,
+    PipelineElementsComponent,
+    PipelineElementsRowComponent,
+    PipelineElementStatisticsComponent,
+    PipelineMonitoringComponent,
+    PipelineStatusComponent,
+    PipelinePreviewComponent,
+    QuickEditComponent,
+    StatusWidgetComponent,
+    BarchartWidgetComponent,
+    SpPipelineDetailsOverviewComponent,
+  ],
+  providers: [],
+  exports: [
+  ]
 })
 export class PipelineDetailsModule {
 
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.scss b/ui/src/app/pipeline-details/pipeline-details.routes.ts
similarity index 81%
copy from ui/src/app/pipeline-details/pipeline-details.component.scss
copy to ui/src/app/pipeline-details/pipeline-details.routes.ts
index a375af7..b9ff036 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.scss
+++ b/ui/src/app/pipeline-details/pipeline-details.routes.ts
@@ -16,7 +16,10 @@
  *
  */
 
-.md-padding {
-  padding: 10px;
-}
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
 
+export class SpPipelineDetailsRoutes {
+
+  static BASE: SpBreadcrumbItem = {label: 'Pipeline Details', link: ['pipelines']};
+
+}
diff --git a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
index ab7a759..01955e5 100644
--- a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
+++ b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
@@ -93,7 +93,7 @@
                     <button color="accent" mat-button mat-icon-button matTooltip="Delete pipeline"
                             matTooltipPosition="above"
                             (click)="pipelineOperationsService.showDeleteDialog(pipeline, refreshPipelinesEmitter)"
-                            data-cy="delete">
+                            data-cy="delete-pipeline">
                         <i class="material-icons">delete</i>
                     </button>
                 </span>
diff --git a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.scss b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.scss
index c2bef23..7f1e843 100644
--- a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.scss
+++ b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.scss
@@ -25,10 +25,10 @@
 }
 
 .mat-row:nth-child(even) {
-  background-color: var(--color-bg-2);
+  background-color: var(--color-bg-1);
 }
 .mat-row:nth-child(odd) {
-  background-color: var(--color-bg-3);
+  background-color: var(--color-bg-2);
 }
 
 .mat-column-status {
diff --git a/ui/src/app/pipelines/dialog/import-pipeline/import-pipeline-dialog.component.html b/ui/src/app/pipelines/dialog/import-pipeline/import-pipeline-dialog.component.html
index 68d73c1..168191f 100644
--- a/ui/src/app/pipelines/dialog/import-pipeline/import-pipeline-dialog.component.html
+++ b/ui/src/app/pipelines/dialog/import-pipeline/import-pipeline-dialog.component.html
@@ -60,9 +60,9 @@
         <button mat-button mat-raised-button class="mat-basic" (click)="back()" *ngIf="!('upload-pipelines'===page)" style="margin-right:10px;">
             Back
         </button>
-        <button mat-button mat-raised-button color="primary" (click)="startImport()"
+        <button mat-button mat-raised-button color="accent" (click)="startImport()"
                 *ngIf="page === 'select-pipelines'">
             Import
         </button>
     </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/ui/src/app/pipelines/dialog/import-pipeline/import-pipeline-dialog.component.ts b/ui/src/app/pipelines/dialog/import-pipeline/import-pipeline-dialog.component.ts
index 9e9626d..b790afa 100644
--- a/ui/src/app/pipelines/dialog/import-pipeline/import-pipeline-dialog.component.ts
+++ b/ui/src/app/pipelines/dialog/import-pipeline/import-pipeline-dialog.component.ts
@@ -78,8 +78,7 @@
     }
 
     toggleSelectedPipeline(pipeline: Pipeline) {
-        console.log(pipeline);
-        if (this.selectedPipelines.some(p => p._id = pipeline._id)) {
+        if (this.selectedPipelines.some(p => p._id === pipeline._id)) {
             this.selectedPipelines.splice(this.selectedPipelines.findIndex(sp => sp._id === pipeline._id), 1);
         } else {
             this.selectedPipelines.push(pipeline);
@@ -87,7 +86,6 @@
     }
 
     storePipelines() {
-        console.log(this.selectedPipelines);
          const promises = [];
          this.selectedPipelines.forEach(pipeline => {
              pipeline._rev = undefined;
diff --git a/ui/src/app/pipelines/dialog/pipeline-notifications/pipeline-notifications.component.html b/ui/src/app/pipelines/dialog/pipeline-notifications/pipeline-notifications.component.html
index 65fdce4..3812194 100644
--- a/ui/src/app/pipelines/dialog/pipeline-notifications/pipeline-notifications.component.html
+++ b/ui/src/app/pipelines/dialog/pipeline-notifications/pipeline-notifications.component.html
@@ -16,10 +16,10 @@
   ~
   -->
 
-<div class="sp-dialog-container">
-    <div class="sp-dialog-content p-15">
+<div class="sp-dialog-container" fxLayout="column">
+    <div class="sp-dialog-content p-15" fxFlex="100" fxLayout="column">
         <div class="info-message">Pipeline health monitoring discovered the following issues:</div>
-        <div class="log-message">
+        <div class="log-message" fxFlex="100" fxLayout="column">
             <span *ngFor="let notification of pipeline.pipelineNotifications">
                 <p>{{notification}}</p>
             </span>
diff --git a/ui/src/app/pipelines/dialog/pipeline-notifications/pipeline-notifications.component.scss b/ui/src/app/pipelines/dialog/pipeline-notifications/pipeline-notifications.component.scss
index 04c6ace..0a47a46 100644
--- a/ui/src/app/pipelines/dialog/pipeline-notifications/pipeline-notifications.component.scss
+++ b/ui/src/app/pipelines/dialog/pipeline-notifications/pipeline-notifications.component.scss
@@ -21,15 +21,15 @@
 
 .log-message {
   background-color: black;
-  font: 1.3rem Inconsolata, monospace;
+  font: 11pt Inconsolata, monospace;
   text-shadow: 0 0 5px #C8C8C8;
   color: white;
   padding: 10px;
-  width: 100%;
+  max-width: 100%;
 }
 
 .info-message {
-  font-size: 1.5rem;
+  font-size: 12pt;
   margin-top: 10px;
   margin-bottom: 5px;
 }
diff --git a/ui/src/app/pipelines/pipelines.component.html b/ui/src/app/pipelines/pipelines.component.html
index cb8f87e..fb08754 100644
--- a/ui/src/app/pipelines/pipelines.component.html
+++ b/ui/src/app/pipelines/pipelines.component.html
@@ -16,65 +16,69 @@
   ~
   -->
 
-<div fxLayout="column" class="page-container">
-    <div fxLayout="row" class="border sp-tab-bg" style="padding:0;">
-        <div fxFlex="100" class="page-container-nav">
-            <div fxFlex="100" fxLayout="row">
-                <button mat-button mat-flat-button color="accent" (click)="showPipelineCategoriesDialog()">Manage Categories</button>
-                <div fxFlex fxLayoutAlign="start center" [attr.id]="'peType'">
-                    <mat-tab-group [selectedIndex]="selectedCategoryIndex" (selectedIndexChange)="setSelectedTab($event)" color="accent">
-                        <mat-tab label="All pipelines"></mat-tab>
-                        <mat-tab *ngFor="let category of pipelineCategories" label="{{category.categoryName}}"></mat-tab>
-                    </mat-tab-group>
+<sp-basic-view [showBackLink]="false" [padding]="true">
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <button mat-button mat-raised-button color="accent" (click)="navigateToPipelineEditor()" data-cy="pipelines-navigate-to-editor">
+            <i class="material-icons">add</i>&nbsp;New pipeline
+        </button>
+        <button class="mr-10" mat-button color="accent" (click)="startAllPipelines(true)"
+                [disabled]="checkCurrentSelectionStatus(false)" *ngIf="hasPipelineWritePrivileges">
+            <mat-icon>play_arrow</mat-icon><span>Start all pipelines</span>
+        </button>
+        <button mat-button color="accent" (click)="startAllPipelines(false)"
+                [disabled]="checkCurrentSelectionStatus(true)" *ngIf="hasPipelineWritePrivileges">
+            <mat-icon>stop</mat-icon>
+            <span>Stop all pipelines</span>
+        </button>
+        <span fxFlex></span>
+        <button mat-button mat-icon-button color="accent" matTooltip="Refresh pipelines" matTooltipPosition="above"
+                (click)="refreshPipelines()">
+            <i class="material-icons">
+                refresh
+            </i>
+        </button>
+        <button mat-button mat-icon-button color="accent" matTooltip="Export pipelines" matTooltipPosition="above"
+                (click)="exportPipelines()">
+            <i class="material-icons">
+                cloud_download
+            </i>
+        </button>
+        <button mat-button mat-icon-button color="accent" matTooltip="Import pipelines" matTooltipPosition="above"
+                (click)="openImportPipelinesDialog()">
+            <i class="material-icons">
+                cloud_upload
+            </i>
+        </button>
+    </div>
+    <div fxFlex="100" fxLayout="column">
+        <div fxLayout="column">
+            <sp-basic-header-title-component title="My pipelines"></sp-basic-header-title-component>
+            <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+                <sp-basic-inner-panel [showTitle]="false" innerPadding="0" outerMargin="0" fxFlex="90"
+                                      [hideToolbar]="true">
+                    <div fxFlex="100">
+                        <pipeline-overview [activeCategoryId]="activeCategoryId" [pipelines]="pipelines"
+                                           [pipelineToStart]="pipelineToStart"
+                                           (refreshPipelinesEmitter)="refreshPipelines()"
+                                           *ngIf="pipelinesReady"></pipeline-overview>
+                    </div>
+                </sp-basic-inner-panel>
+            </div>
+            <div fxFlex="100" fxLayout="column" style="margin-top: 20px;">
+                <sp-basic-header-title-component title="System-generated pipelines"></sp-basic-header-title-component>
+                <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+                    <sp-basic-inner-panel [showTitle]="false" innerPadding="0" outerMargin="0" fxFlex="90"
+                                          [hideToolbar]="true">
+                        <div fxFlex="100">
+                            <pipeline-overview [activeCategoryId]="activeCategoryId" [pipelines]="systemPipelines"
+                                               [pipelineToStart]="systemPipelineToStart"
+                                               (refreshPipelinesEmitter)="refreshPipelines()"
+                                               *ngIf="pipelinesReady"></pipeline-overview>
+                        </div>
+                    </sp-basic-inner-panel>
                 </div>
             </div>
         </div>
     </div>
-    <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100">
-        <div fxLayout="row">
-            <button class="mr-10" mat-button mat-raised-button color="accent" (click)="startAllPipelines(true)"
-                       [disabled]="checkCurrentSelectionStatus(false)" *ngIf="hasPipelineWritePrivileges">Start all pipelines
-            </button>
-            <button mat-button mat-raised-button color="accent" (click)="startAllPipelines(false)"
-                       [disabled]="checkCurrentSelectionStatus(true)" *ngIf="hasPipelineWritePrivileges">Stop all pipelines
-            </button>
-        </div>
-        <div class="assemblyOptions sp-blue-bg mt-20" style="padding:5px;">
-            <div fxLayout="row" fxLayoutAlign="start center">
-                <h4>My pipelines</h4>
-                <span fxFlex></span>
-                <button mat-button mat-icon-button matTooltip="Refresh pipelines" matTooltipPosition="above"
-                        (click)="refreshPipelines()">
-                    <i class="material-icons">
-                        refresh
-                    </i>
-                </button>
-                <button mat-button mat-icon-button matTooltip="Export pipelines" matTooltipPosition="above"
-                        (click)="exportPipelines()">
-                    <i class="material-icons">
-                        cloud_download
-                    </i>
-                </button>
-                <button mat-button mat-icon-button matTooltip="Import pipelines" matTooltipPosition="above"
-                        (click)="openImportPipelinesDialog()">
-                    <i class="material-icons">
-                        cloud_upload
-                    </i>
-                </button>
-            </div>
-        </div>
-        <div class="sp-blue-border">
-            <pipeline-overview [activeCategoryId]="activeCategoryId" [pipelines]="pipelines" [pipelineToStart]="pipelineToStart"
-                              (refreshPipelinesEmitter)="refreshPipelines()" *ngIf="pipelinesReady"></pipeline-overview>
-        </div>
-        <div style="margin-top:20px;margin-bottom:20px;"></div>
-        <div class="assemblyOptions sp-blue-bg">
-            <h4>System-generated pipelines</h4>
-        </div>
-        <div class="sp-blue-border">
-            <pipeline-overview [activeCategoryId]="activeCategoryId" [pipelines]="systemPipelines" [pipelineToStart]="systemPipelineToStart"
-                              (refreshPipelinesEmitter)="refreshPipelines()" *ngIf="pipelinesReady"></pipeline-overview>
-        </div>
-    </div>
-</div>
+</sp-basic-view>
 
diff --git a/ui/src/app/pipelines/pipelines.component.ts b/ui/src/app/pipelines/pipelines.component.ts
index 316810d..c966ff0 100644
--- a/ui/src/app/pipelines/pipelines.component.ts
+++ b/ui/src/app/pipelines/pipelines.component.ts
@@ -19,14 +19,15 @@
 import * as FileSaver from 'file-saver';
 import { Component, OnInit } from '@angular/core';
 import { Pipeline, PipelineCategory, PipelineService } from '@streampipes/platform-services';
-import { DialogService, PanelType, DialogRef } from '@streampipes/shared-ui';
+import { DialogRef, DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
 import { ImportPipelineDialogComponent } from './dialog/import-pipeline/import-pipeline-dialog.component';
 import { StartAllPipelinesDialogComponent } from './dialog/start-all-pipelines/start-all-pipelines-dialog.component';
 import { PipelineCategoriesDialogComponent } from './dialog/pipeline-categories/pipeline-categories-dialog.component';
 import { zip } from 'rxjs';
-import { ActivatedRoute } from '@angular/router';
+import { ActivatedRoute, Router } from '@angular/router';
 import { AuthService } from '../services/auth.service';
 import { UserPrivilege } from '../_enums/user-privilege.enum';
+import { SpPipelineRoutes } from './pipelines.routes';
 
 @Component({
   selector: 'pipelines',
@@ -56,13 +57,16 @@
   constructor(private pipelineService: PipelineService,
               private dialogService: DialogService,
               private activatedRoute: ActivatedRoute,
-              private authService: AuthService) {
+              private authService: AuthService,
+              private router: Router,
+              private breadcrumbService: SpBreadcrumbService) {
     this.pipelineCategories = [];
     this.starting = false;
     this.stopping = false;
   }
 
   ngOnInit() {
+    this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpPipelineRoutes.BASE));
     this.authService.user$.subscribe(user => {
       this.hasPipelineWritePrivileges = this.authService.hasRole(UserPrivilege.PRIVILEGE_WRITE_PIPELINE);
     });
@@ -192,4 +196,8 @@
   showPipeline(pipeline) {
     pipeline.display = !pipeline.display;
   }
+
+  navigateToPipelineEditor() {
+    this.router.navigate(['pipelines', 'create']);
+  }
 }
diff --git a/ui/src/app/pipelines/pipelines.module.ts b/ui/src/app/pipelines/pipelines.module.ts
index 0049362..17ca3ec 100644
--- a/ui/src/app/pipelines/pipelines.module.ts
+++ b/ui/src/app/pipelines/pipelines.module.ts
@@ -39,6 +39,14 @@
 import { PipelineNotificationsComponent } from './dialog/pipeline-notifications/pipeline-notifications.component';
 import { CoreUiModule } from '../core-ui/core-ui.module';
 import { PlatformServicesModule } from '@streampipes/platform-services';
+import { SharedUiModule } from '../../../projects/streampipes/shared-ui/src/lib/shared-ui.module';
+import { EditorModule } from '../editor/editor.module';
+import { PipelineDetailsModule } from '../pipeline-details/pipeline-details.module';
+import { RouterModule } from '@angular/router';
+import { EditorComponent } from '../editor/editor.component';
+import { SpPipelineDetailsOverviewComponent } from '../pipeline-details/components/overview/pipeline-details-overview.component';
+import { PipelineMonitoringComponent } from '../pipeline-details/components/monitoring/pipeline-monitoring.component';
+import { QuickEditComponent } from '../pipeline-details/components/edit/quickedit.component';
 
 @NgModule({
   imports: [
@@ -53,6 +61,50 @@
     MatTableModule,
     CoreUiModule,
     PlatformServicesModule,
+    EditorModule,
+    PipelineDetailsModule,
+    SharedUiModule,
+    RouterModule.forChild([
+      {
+        path: 'pipelines',
+        children: [
+          {
+            path: '',
+            component: PipelinesComponent
+          },
+          {
+            path: 'details/:pipelineId',
+            children: [
+              {
+                path: '',
+                redirectTo: 'overview',
+                pathMatch: 'full'
+              },
+              {
+                path: 'overview',
+                component: SpPipelineDetailsOverviewComponent,
+              },
+              {
+                path: 'monitoring',
+                component: PipelineMonitoringComponent,
+              },
+              {
+                path: 'quick-edit',
+                component: QuickEditComponent,
+              }
+            ]
+          },
+          {
+            path: 'create',
+            component: EditorComponent
+          },
+          {
+            path: 'modify/:pipelineId',
+            component: EditorComponent
+          }
+        ]
+      }
+    ]),
   ],
   declarations: [
     DeletePipelineDialogComponent,
diff --git a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss b/ui/src/app/pipelines/pipelines.routes.ts
similarity index 81%
copy from ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
copy to ui/src/app/pipelines/pipelines.routes.ts
index 58ba04b..5b4ccc7 100644
--- a/ui/src/app/connect/components/schema-editor/error-message/error-message.component.scss
+++ b/ui/src/app/pipelines/pipelines.routes.ts
@@ -16,3 +16,10 @@
  *
  */
 
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+
+export class SpPipelineRoutes {
+
+  static BASE: SpBreadcrumbItem = {label: 'Pipelines', link: ['pipelines']};
+
+}
diff --git a/ui/src/app/pipelines/services/pipeline-operations.service.ts b/ui/src/app/pipelines/services/pipeline-operations.service.ts
index 0135fca..997d0f1 100644
--- a/ui/src/app/pipelines/services/pipeline-operations.service.ts
+++ b/ui/src/app/pipelines/services/pipeline-operations.service.ts
@@ -141,12 +141,12 @@
     });
   }
 
-  showPipelineInEditor(id) {
-    this.router.navigate(['editor'], { queryParams: { pipeline: id }});
+  showPipelineInEditor(id: string) {
+    this.router.navigate(['pipelines', 'modify', id]);
   }
 
-  showPipelineDetails(id) {
-    this.router.navigate(['pipeline-details'], { queryParams: { pipeline: id }});
+  showPipelineDetails(id: string) {
+    this.router.navigate(['pipelines', 'details', id]);
   }
 
   modifyPipeline(pipeline) {
diff --git a/ui/src/app/profile/profile.component.ts b/ui/src/app/profile/profile.component.ts
index 2687fb7..84dd97e 100644
--- a/ui/src/app/profile/profile.component.ts
+++ b/ui/src/app/profile/profile.component.ts
@@ -17,6 +17,7 @@
  */
 
 import { Component, OnInit } from '@angular/core';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
 
 @Component({
   selector: 'profile',
@@ -27,7 +28,11 @@
 
   selectedIndex = 0;
 
+  constructor(private breadcrumbService: SpBreadcrumbService) {
+  }
+
   ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb([{label: 'Profile'}]);
   }
 
   selectedIndexChange(index: number) {
diff --git a/ui/src/app/services/auth.service.ts b/ui/src/app/services/auth.service.ts
index ab8d5e7..feb406d 100644
--- a/ui/src/app/services/auth.service.ts
+++ b/ui/src/app/services/auth.service.ts
@@ -177,6 +177,8 @@
                 return this.hasAnyRole(['ROLE_ADMIN']);
             case PageName.NOTIFICATIONS:
                 return this.hasAnyRole(['ROLE_PIPELINE_ADMIN']);
+            case PageName.ASSETS:
+                return this.hasAnyRole(['ROLE_ADMIN']);
             case PageName.SETTINGS:
                 return this.hasAnyRole(['ROLE_ADMIN']);
             default:
diff --git a/ui/src/assets/img/favicon/android-icon-144x144.png b/ui/src/assets/img/favicon/android-icon-144x144.png
deleted file mode 100644
index f7bb667..0000000
--- a/ui/src/assets/img/favicon/android-icon-144x144.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/android-icon-192x192.png b/ui/src/assets/img/favicon/android-icon-192x192.png
deleted file mode 100644
index 3cb803c..0000000
--- a/ui/src/assets/img/favicon/android-icon-192x192.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/android-icon-36x36.png b/ui/src/assets/img/favicon/android-icon-36x36.png
deleted file mode 100644
index 937f4c1..0000000
--- a/ui/src/assets/img/favicon/android-icon-36x36.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/android-icon-48x48.png b/ui/src/assets/img/favicon/android-icon-48x48.png
deleted file mode 100644
index f293d4c..0000000
--- a/ui/src/assets/img/favicon/android-icon-48x48.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/android-icon-72x72.png b/ui/src/assets/img/favicon/android-icon-72x72.png
deleted file mode 100644
index 371718e..0000000
--- a/ui/src/assets/img/favicon/android-icon-72x72.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/android-icon-96x96.png b/ui/src/assets/img/favicon/android-icon-96x96.png
deleted file mode 100644
index 92f2f5a..0000000
--- a/ui/src/assets/img/favicon/android-icon-96x96.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-114x114.png b/ui/src/assets/img/favicon/apple-icon-114x114.png
deleted file mode 100644
index c46d66d..0000000
--- a/ui/src/assets/img/favicon/apple-icon-114x114.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-120x120.png b/ui/src/assets/img/favicon/apple-icon-120x120.png
deleted file mode 100644
index e534180..0000000
--- a/ui/src/assets/img/favicon/apple-icon-120x120.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-144x144.png b/ui/src/assets/img/favicon/apple-icon-144x144.png
deleted file mode 100644
index f7bb667..0000000
--- a/ui/src/assets/img/favicon/apple-icon-144x144.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-152x152.png b/ui/src/assets/img/favicon/apple-icon-152x152.png
deleted file mode 100644
index f602ff3..0000000
--- a/ui/src/assets/img/favicon/apple-icon-152x152.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-180x180.png b/ui/src/assets/img/favicon/apple-icon-180x180.png
deleted file mode 100644
index e737774..0000000
--- a/ui/src/assets/img/favicon/apple-icon-180x180.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-57x57.png b/ui/src/assets/img/favicon/apple-icon-57x57.png
deleted file mode 100644
index 251772f..0000000
--- a/ui/src/assets/img/favicon/apple-icon-57x57.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-60x60.png b/ui/src/assets/img/favicon/apple-icon-60x60.png
deleted file mode 100644
index ecc0c22..0000000
--- a/ui/src/assets/img/favicon/apple-icon-60x60.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-72x72.png b/ui/src/assets/img/favicon/apple-icon-72x72.png
deleted file mode 100644
index 371718e..0000000
--- a/ui/src/assets/img/favicon/apple-icon-72x72.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-76x76.png b/ui/src/assets/img/favicon/apple-icon-76x76.png
deleted file mode 100644
index 3ed8f32..0000000
--- a/ui/src/assets/img/favicon/apple-icon-76x76.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon-precomposed.png b/ui/src/assets/img/favicon/apple-icon-precomposed.png
deleted file mode 100644
index d81fe77..0000000
--- a/ui/src/assets/img/favicon/apple-icon-precomposed.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/apple-icon.png b/ui/src/assets/img/favicon/apple-icon.png
deleted file mode 100644
index d81fe77..0000000
--- a/ui/src/assets/img/favicon/apple-icon.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/favicon-16x16.png b/ui/src/assets/img/favicon/favicon-16x16.png
deleted file mode 100644
index 8487ca2..0000000
--- a/ui/src/assets/img/favicon/favicon-16x16.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/favicon-32x32.png b/ui/src/assets/img/favicon/favicon-32x32.png
deleted file mode 100644
index 11587ee..0000000
--- a/ui/src/assets/img/favicon/favicon-32x32.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/ms-icon-144x144.png b/ui/src/assets/img/favicon/ms-icon-144x144.png
deleted file mode 100644
index f7bb667..0000000
--- a/ui/src/assets/img/favicon/ms-icon-144x144.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/ms-icon-150x150.png b/ui/src/assets/img/favicon/ms-icon-150x150.png
deleted file mode 100644
index 98e5129..0000000
--- a/ui/src/assets/img/favicon/ms-icon-150x150.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/ms-icon-310x310.png b/ui/src/assets/img/favicon/ms-icon-310x310.png
deleted file mode 100644
index b9b4fa9..0000000
--- a/ui/src/assets/img/favicon/ms-icon-310x310.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/img/favicon/ms-icon-70x70.png b/ui/src/assets/img/favicon/ms-icon-70x70.png
deleted file mode 100644
index 67ae884..0000000
--- a/ui/src/assets/img/favicon/ms-icon-70x70.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/scss/_variables.scss b/ui/src/scss/_variables.scss
index e440d68..5d137a4 100644
--- a/ui/src/scss/_variables.scss
+++ b/ui/src/scss/_variables.scss
@@ -16,7 +16,7 @@
  *
  */
 
-$sp-color-primary:  rgb(57, 181, 74);
+$sp-color-primary: rgb(57, 181, 74);
 $sp-color-primary-light: rgb(59, 205, 76);
 $sp-color-accent: #1b1464;
 $sp-color-accent-light-blue: rgb(59, 92, 149);
@@ -29,3 +29,14 @@
 $sp-color-sink: #3F51B5;
 
 $sp-color-error: #B71C1C;
+
+body {
+  --color-data-view: rgb(122, 206, 227);
+  --color-dashboard: rgb(76, 115, 164);
+  --color-adapter: rgb(182, 140, 97);
+  --color-data-source: #ffa23b;
+  --color-pipeline: rgb(102, 185, 114);
+  --color-measurement: rgb(39, 164, 155);
+  --color-file: rgb(163, 98, 190);
+
+}
diff --git a/ui/src/scss/main.scss b/ui/src/scss/main.scss
index 083b9b7..c50faa0 100644
--- a/ui/src/scss/main.scss
+++ b/ui/src/scss/main.scss
@@ -37,7 +37,6 @@
 
 @import './sp/main';
 @import './sp/data-explorer';
-@import './sp/loading-bar';
 @import './sp/buttons';
 @import './sp/buttons.ng1';
 @import './sp/spinner';
diff --git a/ui/src/scss/sp/layout.scss b/ui/src/scss/sp/layout.scss
index 2ed1065..408188e 100644
--- a/ui/src/scss/sp/layout.scss
+++ b/ui/src/scss/sp/layout.scss
@@ -88,6 +88,9 @@
   margin-right: 5px;
 }
 
+.ml-5 {
+  margin-left: 5px;
+}
 
 .mr-15 {
   margin-right: 15px;
@@ -163,3 +166,40 @@
 .mat-expansion-panel-body {
   padding: 0 !important;
 }
+
+.small-select mat-select {
+  background-color: rgba(58, 40, 8, 0.12);
+  padding: 6px 10px 6px 10px;
+  box-sizing: border-box;
+  border-radius: 5px;
+}
+
+.small-select .mat-select-value {
+  font-size: 16px;
+  color: var(--color-accent);
+}
+
+.small-select .mat-form-field-underline {
+  display: none;
+}
+
+.small-select mat-select-trigger div>i {
+  margin-right: 8px;
+}
+
+.small-select .mat-form-field-infix {
+  padding: 0;
+  border-top: 0;
+}
+
+.small-select .mat-form-field-wrapper {
+  padding-bottom: 0;
+}
+
+.large-checkbox .mat-checkbox-inner-container {
+  width: 20px;
+  height: 20px;
+}
+
+.mat-menu-panel.large-menu { max-width: none; }
+
diff --git a/ui/src/scss/sp/loading-bar.scss b/ui/src/scss/sp/loading-bar.scss
deleted file mode 100644
index e50006b..0000000
--- a/ui/src/scss/sp/loading-bar.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements.  See the NOTICE file distributed with
- *   this work for additional information regarding copyright ownership.
- *   The ASF licenses this file to You under the Apache License, Version 2.0
- *   (the "License"); you may not use this file except in compliance with
- *   the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing, software
- *   distributed under the License is distributed on an "AS IS" BASIS,
- *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *   See the License for the specific language governing permissions and
- *   limitations under the License.
- */
-
-#loading-bar .bar {
-  -webkit-transition: width 350ms;
-  -moz-transition: width 350ms;
-  -o-transition: width 350ms;
-  transition: width 350ms;
-
-  background: $sp-color-accent;
-  position: fixed;
-  z-index: 10002;
-  top: 0px;
-  left: 0;
-  width: 100%;
-  height: 3px;
-  border-bottom-right-radius: 1px;
-  border-top-right-radius: 1px;
-}
-
-#loading-bar-spinner .spinner-icon {
-  width: 14px;
-  height: 14px;
-
-  border:  solid 2px transparent;
-  border-top-color:  $sp-color-accent;
-  border-left-color: $sp-color-accent;
-  border-radius: 50%;
-
-  -webkit-animation: loading-bar-spinner 400ms linear infinite;
-  -moz-animation:    loading-bar-spinner 400ms linear infinite;
-  -ms-animation:     loading-bar-spinner 400ms linear infinite;
-  -o-animation:      loading-bar-spinner 400ms linear infinite;
-  animation:         loading-bar-spinner 400ms linear infinite;
-}
\ No newline at end of file
diff --git a/ui/src/scss/sp/main.scss b/ui/src/scss/sp/main.scss
index 69dfbbb..a934bee 100644
--- a/ui/src/scss/sp/main.scss
+++ b/ui/src/scss/sp/main.scss
@@ -367,10 +367,14 @@
 .page-container {

   margin: 10px;

   border: 1px solid var(--color-bg-3);

-  min-height: calc(100% - 20px);

+  min-height: calc(100% - 60px);

   //height: 100%;

 }

 

+.sp-full-height {

+  min-height: calc(100% - 20px);

+}

+

 .page-container-padding-inner {

   margin: 10px;

 }

@@ -911,7 +915,7 @@
   padding: 5px;

   border: 1px solid var(--color-bg-2);

   height: 300px;

-  width: 100%;

+  max-width: 100%;

 

   background-color: var(--color-bg-1);

   background-image: var(--canvas-color);

diff --git a/ui/src/scss/sp/mat-tab.scss b/ui/src/scss/sp/mat-tab.scss
index 6549b2e..66c20ba 100644
--- a/ui/src/scss/sp/mat-tab.scss
+++ b/ui/src/scss/sp/mat-tab.scss
@@ -18,4 +18,10 @@
 
 .mat-tab-label-content {
   text-transform: uppercase;
-}
\ No newline at end of file
+}
+
+.small .mat-tab-label {
+  min-width: 100px;
+  height: 32px;
+  font-size: 10pt;
+}
diff --git a/ui/src/scss/sp/widgets.scss b/ui/src/scss/sp/widgets.scss
index 58f8c6e..fca4f06 100644
--- a/ui/src/scss/sp/widgets.scss
+++ b/ui/src/scss/sp/widgets.scss
@@ -42,14 +42,17 @@
 
 .general-options-panel {
   margin-top: 4px;
-  margin-bottom: 4px;
+  margin-bottom: 8px;
   border: 1px solid var(--color-bg-3);
   background: var(--color-bg-1);
   padding: 5px;
 }
 
 .general-options-header {
-  margin-right: 10px;
+  //margin-right: 10px;
   margin-bottom: 10px;
   font-weight: bold;
+  border-left: 4px solid var(--color-primary);
+  padding-left: 5px;
+  font-size: 13pt;
 }
diff --git a/ui/webpack.partial.base.js b/ui/webpack.partial.base.js
index f2930c2..6e34715 100644
--- a/ui/webpack.partial.base.js
+++ b/ui/webpack.partial.base.js
@@ -66,9 +66,15 @@
                 "@angular/forms": { singleton: true, strictVersion: true, requiredVersion: 'auto' , eager: true},
                 "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' , eager: true},
                 "@angular/cdk": { singleton: true, strictVersion: true, requiredVersion: 'auto' , eager: true},
+                "@angular/cdk/overlay": { singleton: true, strictVersion: false, requiredVersion: 'auto', eager: true},
+                "@angular/cdk/portal": { singleton: true, strictVersion: false, requiredVersion: 'auto', eager: true},
                 "@angular/material": { singleton: true, strictVersion: true, requiredVersion:'auto', eager: true},
+                "@angular/material/core": { singleton: true, strictVersion: false, requiredVersion: 'auto', eager: true},
+                "@angular/material/menu": { singleton: true, strictVersion: false, requiredVersion: 'auto', eager: true},
                 "@angular/material/tooltip": { singleton: true, strictVersion: true, requiredVersion:'auto', eager: true },
                 "@angular/material/dialog": { singleton: true, strictVersion: true, requiredVersion:'auto', eager: true },
+                "@angular/material/select": { singleton: true, strictVersion: true, requiredVersion:'auto', eager: true },
+                "@angular/material/form-field": { singleton: true, strictVersion: true, requiredVersion:'auto', eager: true },
                 "@streampipes/shared-ui": { singleton: true, strictVersion: true, eager: true},
                 "@streampipes/platform-services": { singleton: true, strictVersion: true, eager: true},
                 ...sharedMappings.getDescriptors()